我在bash变量扩展中遇到了一些分词问题。我希望能够在变量中存储一个参数列表并运行它,但任何引用的多字参数都不会评估我对它的期望。
我将用一个例子来解释我的问题。假设我有一个函数decho
,它在每行上打印每个位置参数:
#!/bin/bash -u
while [ $# -gt 0 ]; do
echo $1
shift
done
好的,如果我去decho a b "c d"
我得到:
[~]$ 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
但这看起来有点笨重。是否有更好的方法可以使$args
decho $args
的扩展按照我的预期进行分词?
答案 0 :(得分:5)
您可以使用:
eval decho $args
答案 1 :(得分:2)
您可以在脚本中移动eval:
#!/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
答案 2 :(得分:0)
你试过了吗?
for arg in "$@"
do
echo "arg $i:$arg:"
let "i+=1"
done
应该产生类似的东西:
arg 1: a
arg 2: c d
在你的情况下。
直接记忆,不保证: - )
答案 3 :(得分:0)
嗯.. eval decho $args
也有效:
[~]$ eval decho $args
a
b
c d
我可以使用"${array[@]}"
(类似于"$@"
)对bash数组做一些事情,但是我必须编写代码来加载数组,这将是一件痛苦的事。
答案 4 :(得分:0)
尝试将存储在变量中的参数列表传递给命令存在根本缺陷。
据推测,如果你有代码在某处创建一个包含预期args的变量。对于命令,您可以将其更改为将args存储到数组变量中:
decho_argv=(a b 'c d') # <-- easy!
然后,不是改变命令“decho”来容纳从普通变量中获取的args(它将破坏它处理普通args的能力),你可以这样做:
decho "${decho_argv[@]}" # USE DOUBLE QUOTES!!!
但是,如果您正在尝试获取任意输入(预期是与预期命令位置参数对应的字符串字段),并且您希望将这些参数传递给命令,那么您应该不使用变量,将数据读入数组。
请注意,提供使用eval来设置位置参数和普通变量内容的建议非常危险。
因为,将变量的内容暴露给命令行中的引用删除和分词不能保护变量中字符串中的shell元字符不会造成破坏。
,例如,在下面的例子中,如果单词“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