我写了一个脚本,可以为我生成引号
如果输出正确地引用了外壳,并且您信任该输出,则可以eval
在其上运行。
假设您有一个支持数组的外壳,那么最好使用一个外壳来存储您得到的参数。
如果./gen_args.sh
产生类似的输出'foo bar' '*' asdf
,则可以运行eval "args=( $(./gen_args.sh) )"
以结果填充名为的数组args
。这将是三个元素foo bar
,*
,asdf
。
我们可以"${args[@]}"
像往常一样使用以分别扩展数组元素:
$ eval "args=( $(./gen_args.sh) )"
$ for var in "${args[@]}"; do printf ":%s:\n" "$var"; done
:foo bar:
:*:
:asdf:
(请注意引号。"${array[@]}"
未更改的引数扩展为所有元素。不带引号的数组元素将进行单词拆分。请参阅例如BashGuide的Arrays页面。)
但是,eval
它将愉快地运行任何shell替换,因此$HOME
在输出中将扩展到您的主目录,并且命令替换实际上将在shell运行中运行命令eval
。的输出"$(date >&2)"
将创建一个空数组元素,并在stdout上打印当前日期。如果gen_args.sh
要从某个不受信任的来源(例如网络上的另一台主机)获取其他用户创建的文件名来获取数据,这将是一个问题。输出可以包括任意命令。(如果get_args.sh
本身是恶意的,则不需要输出任何东西,它可以直接运行恶意命令。)
如果不使用eval很难解析shell引用,则可以在脚本输出中使用其他一些字符作为分隔符。您需要选择实际参数中不需要的一个。
让我们选择#
,并输出脚本foo bar#*#asdf
。现在,我们可以使用无引号的命令扩展将命令的输出拆分为参数。
$ IFS='#' # split on '#' signs
$ set -f # disable globbing
$ args=( $( ./gen_args3.sh ) ) # assign the values to the array
$ for var in "${args[@]}"; do printf ":%s:\n" "$var"; done
:foo bar:
:*:
:asdf:
IFS
如果您依赖脚本中其他位置的分词,则需要稍后再进行设置(unset IFS
应该将其设置为默认值),并且set +f
如果您以后要使用遍历功能,也需要使用。
如果您不使用Bash或其他具有数组的外壳,则可以使用位置参数。替换为args=( $(...) )
,set -- $(./gen_args.sh)
然后使用"$@"
代替"${args[@]}"
。(在这里,您也需要在引号周围"$@"
加上引号,否则位置参数将受到单词拆分的影响。)
eval
可以使用它,但是通常不建议这样做。xargs
也是要考虑的事情