如何在bash中通过变量传递带空格的命令行参数

5
我希望能够从文件中读取命令行参数并使用它们来调用命令。因此,我需要通过bash变量传递这些参数。问题在于一些参数中包含空格。我该怎么办?
以下是一个示例代码,用于说明问题:
file.txt的内容(引号只是为了显示两个不同的参数):
"aaa bbb" "xxx yyy"

Shell脚本:

ARGS=$(cat file.txt)
/some/command $ARGS

/some/command 应该接收两个参数: aaa bbbxxx yyy。我可以控制生成的 file.txt 文件和 shell 脚本本身。


我认为文件内容对正确答案有很大影响。你能在file.txt中添加一些更多的数据吗(例如几行)? - George Vasiliou
请问您是否打算将"aaa bbb" "xxx yyy"作为一个单独参数(带有文字引号)传递到您的命令中,还是应该将其解释为两个具有各自值的参数aaa bbbxxx yyy - Fred
@GeorgeVasiliou 正如我所写的那样,我对生成的文件和脚本拥有完全控制权。我可以向它们写入任何内容。 - Smilediver
@Fred 引用只是为了说明两个不同的参数。 - Smilediver
你从错误的前提出发,认为这种类型的配置文件是一个好主意;但实际上并不是。 - chepner
2个回答

4
如果您想针对在file.txt中找到的每一行执行命令,使每一行成为一个单独的参数集,请按照以下方式操作:
xargs /some/command <file.txt
xargs实用程序接收标准输入中的每一行,并使用其内容作为要提供给调用的命令的参数。如果文件只包含一行,则它将仅工作并仅执行一次命令。
以下解决方案也可以完成相同的任务,但还适用于函数:
while IFS= read -r line
do
  eval args=\("$line"\)
  command_or_function "${args[@]}"
done<file.txt

请注意,这里使用了eval,这意味着如果file.txt文件中包含恶意内容,则可能导致任意代码执行。您必须百分之百确定文件中的数据是安全的。
此技术的思路是将每行文本拆分成一个数组(一个数组元素是一个参数),然后使用数组扩展("${args[@]}")展开它的所有元素列表,并正确引用(这里引号很重要)。
另外,eval行可以被替换为:
declare -a args=\($line\)

但是$line仍然会被扩展,所以这并不比eval更安全。

更新修复了,太好了!但是这个微不足道的任务并不需要 eval,可以像我的答案一样简单地解决。 - Inian
@Inian,请解释哪些引号被剥离了?如果您正在谈论基于数组的解决方案,请尝试一下:数组拆分将遵守文件中的引用(例如,示例数据将创建一个具有两个元素的数组),并且数组扩展也将生成两个参数传递给命令。 - Fred
我是指xargs中的逻辑,请尝试xargs echo < file.txt - Inian
1
@Fred 是的,readarray 现在可以正常工作了,我测试过了。你仍然可以避免使用 eval 并避免恶意代码执行,只需使用 declare -a args=\(......\) 即可。我已经测试过并得到了相同的结果。 - George Vasiliou
1
@Fred 欢迎 :-) 说实话,这只是一个高评分的SO用户在另一个问题下提出的一个建议,目的是避免使用 eval 。我也尝试过 declare -a args +=\(...\) 来添加数组,在我的测试中仍然正常工作。 - George Vasiliou
显示剩余5条评论

2
使用命令替换,将文件内容扩展为命令。
/some/command "$(<file.txt)"

作为一个例子,
cat file
"aaa bbb" "xxx yyy"

如果使用catprintf的不正确组合,将会产生以下结果:

printf "%s\n" $(cat file)
"aaa
bbb"
"xxx
yyy"

适当使用引号时,参数被发送时不会被分割。

printf "%s\n" "$(<file)"
"aaa bbb" "xxx yyy"

OP想要传递包含空格的参数,但我认为他还想用引号括起来数据文件中的参数(从而允许一行上有多个参数)。因此,我的理解是双引号不是参数值的一部分,只是分隔符(就像普通命令中一样)。你的方法将引号作为整行字符串的一部分传递,没有分割。 - Fred
@Fred:他还想将参数与引号一起封装在数据文件中(从而允许在同一行上输入多个参数)这一事实只是一个纯粹的假设,OP从未提出,请遵循明确的要求。 - Inian
@Fred:你能否好心把你的评论“它并没有真正起作用”删除掉? - Inian

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