将环境变量设置为一个大值 -> "参数列表太长"

13

在bash脚本中,我设置了一个环境变量来存储一个包含100万个字符的字符串。我是这样做的:

export LG=XXXXXXX # ... 1 million X's

紧接着这个,我能够毫不费力地回响它,也就是说:

echo $LG

然而,在脚本中运行此命令后,我尝试运行的其他无关命令均失败并显示“参数列表过长”错误。例如:

cat randomfile.txt
/bin/cat: Argument list too long

我阅读了其他帖子,建议使用xargs来解决此问题,但我没有成功。如果我使用除echo以外的任何命令,即使在设置$LG变量后实际上不使用它,我也会收到“参数列表过长”的错误。当然,我想使用$LG变量,但即使在设置后不使用它,该错误也会发生。

任何提示将不胜感激,谢谢!

编辑:

我试图解决的整体问题类似于这样:

我有一个文本文件,需要尽可能保持较小(即几MB)。此文本文件包含一组嵌套在特定网络协议中(即标题、消息长度、消息本身)的消息。消息本身可以是具有100万个或更多字符长度的字符串。因此,为了使原始文件大小保持较小,而不是在文件中有多个大型消息的副本,我使用映射。例如,如果我在消息字段中看到字母A,那么我就使用sed查找并替换A为1百万个X。就像这样:

cat file.txt | sed "s/A/$LG/g"  # Replace A with 1 million X's

我最终将在(非常慢的)模拟器内运行此操作,因此需要尽可能少的周期完成此操作。换句话说,使用循环和1百万次计数器来动态生成1百万个X的实用程序(如awk)将太慢。这就是为什么我认为环境变量解决方案最好。


3
这个变量的目的是什么?值得注意的是,只有环境变量会使用这个有限的空间池;如果您不需要将此变量导出到环境中,并且可以将其保留在本地shell中,则此问题很快就会变得无关紧要。 - Charles Duffy
1
虽然在这个问题上,如果您不需要将其导出到环境中,应该选择一个不同的名称;按约定,全大写名称保留用于环境变量和shell内置函数。 - Charles Duffy
2
这个解释并没有让我明白为什么你需要一个环境变量。sed "s/A/$LG/g" 并不会在环境中查找 LG 的值;它只是替换一个普通的 shell 变量;你可以设置 LG=... 而不需要任何 export,仍然可以以这种方式使用它。(请注意,你可能会因为 sed 命令太大而无法存储在命令行上而遇到麻烦,但你可以通过将要运行的脚本传递给 sed 通过文件描述符来解决这个问题)。 - Charles Duffy
2
我已经更新了我的答案,添加了一个部分,展示了一种建议的方法,可以避免依赖命令行或环境来获取这个值。 - Charles Duffy
2
顺便说一下,我要抱怨一下 shell 中盛行的模仿式编程现象——在这种情况下,人们会复制“export”命令,却不知道它的作用以及何时何地使用它,同样重要的是,也不知道在哪里和何时不要使用它。 - Charles Duffy
显示剩余4条评论
1个回答

16
命令行参数和环境变量都来自同一池的空间。如果设置的环境变量太长,就没有足够的空间容纳命令行参数 -- 即使是将命令行调用分解为更小的分组以适应池中空间的 xargs 也无法在池完全满时运行。
因此:不要这样做。例如,您可以将数据存储在文件中,并在环境中导出该文件的路径。
顺便说一下 -- echo 能够工作的原因是它内置于您的 shell 中。因此,
echo "$LG"

...不需要启动外部进程,因此在进程启动时对参数列表长度和环境变量大小的限制不适用。

另一方面,如果你运行

/bin/echo "$LG"

如果你这样做,那么问题会再次出现。


考虑到问题的实际目标已经在问题中得到了解释,让我建议一种方法,这种方法既不需要环境空间也不需要命令行空间:

#!/bin/bash
#      ^-- also consider ksh; faster than bash, but also supports <()
#          /bin/sh is not usable here, as POSIX sh does not specify <().

lg=... ## DO NOT USE export HERE!
sed -f <(printf '%s\n' "s/A/$lg/g")

我明白了。你的意思是 sed -f <(printf '%s\n' "s/A/$lg/g") fileOfMessages.txt,对吗?我认为这似乎可以解决问题。非常感谢! - Ivan Stalev
1
很高兴听到这个方法有效!请随意将答案标记为已接受。(至于 fileOfMessages.txt,您在问题中没有指定是通过标准输入流还是命名参数提供输入,因此我故意保持了答案的不可知性)。 - Charles Duffy
能否知道限制有多大? - lindhe
3
getconf ARG_MAX 显示总池大小。 - Charles Duffy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接