[英]How can I pass a complete argument list in bash while keeping mulitword arguments together?
我在bash变量扩展中遇到单词拆分问题。 我希望能够将参数列表存储在变量中并运行它,但是任何带引号的多字参数都无法评估我的期望。
我将用一个例子来解释我的问题。 可以说我有一个函数decho
,它在自己的行上打印了每个位置参数:
#!/bin/bash -u
while [ $# -gt 0 ]; do
echo $1
shift
done
好吧,如果我去decho ab "cd"
我得到:
[~]$ decho a b "c d"
a
b
c d
这是我期望和想要的。 但是另一方面,如果我从变量获取参数列表,则会得到以下信息:
[~]$ args='a b "c d"'
[~]$ decho $args
a
b
"c
d"
这不是我想要的。 我可以去:
[~]$ echo decho $args | bash
a
b
c d
但这似乎有些笨拙。 有没有更好的方法可以使decho $args
的$args
扩展按我期望的方式拆分?
您可以使用:
eval decho $args
您可以在脚本内移动评估:
#!/bin/bash -u
eval set -- $*
for i;
do
echo $i;
done
现在您可以执行以下操作:
$ args='a b "c d"'
$ decho $args
a
b
c d
但是如果在CL上传递参数,则必须引用这些参数:
$ decho 'a b "c d"'
a
b
c d
从根本上说,试图将存储在变量中的参数列表传递给命令是有缺陷的。
大概,如果您在某处有代码来创建一个包含预期参数的变量。 对于命令,则可以将其更改为将args存储到数组变量中:
decho_argv=(a b 'c d') # <-- easy!
然后,可以执行以下操作,而不是更改命令“ decho”以容纳从普通变量中获取的args(这将破坏其处理常规args的能力):
decho "${decho_argv[@]}" # USE DOUBLE QUOTES!!!
但是,如果您正在尝试采用任意输入(预期是与预期的命令位置参数相对应的字符串字段)的情况,并且想要将这些参数传递给命令,则应该使用变量而不是变量,数据放入数组。
请注意,建议使用eval来设置具有普通变量内容的位置参数非常危险。
因为,在命令行上将变量的内容暴露于引号删除和单词拆分的过程中,无法防止变量字符串中的shell metachar引起破坏。
例如,假设在下面的示例中,是否将单词“ man”替换为两个单词“ rm”和“ -rf”,而最后一个arg单词为“ *”:
不要这样做:
> args='arg1 ; man arg4'
> eval set -- $args
No manual entry for arg4
> eval set -- "$args" # This is no better
No manual entry for arg4
> eval "set -- $args" # Still hopeless
No manual entry for arg4
> eval "set -- '$args'" # making it safe also makes it not work at all!
> echo "$1"
arg1 ; man arg4
你有没有尝试过:
for arg in "$@"
do
echo "arg $i:$arg:"
let "i+=1"
done
应该产生如下内容:
arg 1: a
arg 2: c d
在你的情况下。
直接从内存中,不能保证:-)
eval decho $args
.. eval decho $args
也可以:
[~]$ eval decho $args
a
b
c d
而且我也许可以使用"${array[@]}"
(类似于"$@"
)对bash数组进行某些操作,但是随后我将不得不编写代码来加载数组,这很痛苦。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.