You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何无需eval,用含参字符串按Bash逻辑调用脚本或转参数数组?

期望结果

是否可以使用包含参数的字符串调用脚本?

str_params="this/one 'that one' and \"yet another\""

以下函数会在stdout打印参数的接收情况:

display_args () {
  all_args=("${0}" "${@}")
  for i in "${!all_args[@]}"; do 
    printf "  $%d is '%q'\n" "${i}" "${!i}"
  done
}

期望得到如下结果,此处使用了数组展开(用ary_params替代str_params):

ary_params=(this/one 'that one' and "yet another")
display_args "${ary_params[@]}"
 $0 is 'bash'
 $1 is 'this/one'
 $2 is 'that\ one'
 $3 is 'and'
 $4 is 'yet\ another'

遇到的问题

首次尝试使用str_params时,无论单双引号如何,字符串都会按空格分割为参数:

$ display_args ${str_params}
 $0 is 'bash'
 $1 is 'this/one'
 $2 is '\'that'
 $3 is 'one\''
 $4 is 'and'
 $5 is '\"yet'
 $6 is 'another\"'

第二次尝试报错,Bash确实会将整个字符串当作文件名查找:

$ cmd="display_args ${str_params}"
$ echo "${cmd}"
display_args this/one 'that one' and "yet another"
$ "$cmd"
bash: display_args this/one 'that one' and "yet another": No such file or directory
  • 直接调用$cmd(不加双引号)会回到首次尝试的结果。

调研情况

该问题已有不少相关文档和讨论,列举如下:

  1. 一份FAQ建议构建参数数组并展开元素,提及了参数展开的注意事项、IFS= read -r相关内容及其他无关示例。关于向Bash脚本传递数组参数,有回答明确说明此方法在某些场景下可行,但并非通用方案(还引用了Bash作者的话:没有很好的方法将数组变量编码到环境中)。
  2. 有回答(Bash按引号分割行转为参数)清晰说明了Shell处理命令与字符串的区别:Shell在执行命令前的最后一步执行引号移除。但解析str_params变量时,Shell将引号视为普通字符,不会执行引号移除。同一帖子的另一回答给出了重写参数列表的示例,但不确定是否通用。
  3. 另一回答(如何在Bash脚本中遍历参数)解释了Shell先处理引号再展开变量,要让Shell注意变量(如上述str_params和cmd)中的引号,需使用eval。但eval的使用存在风险,因此怀疑是否有更简单的替代方案。

使用eval的效果

按照上述示例尝试eval,结果符合预期:

$ echo "$cmd"
display_args this/one 'that one' and "yet another"
$ eval $cmd
 $0 is 'bash'
 $1 is 'this/one'
 $2 is 'that\ one'
 $3 is 'and'
 $4 is 'yet\ another'
$ eval display_args $str_params
 $0 is 'bash'
 $1 is 'this/one'
 $2 is 'that\ one'
 $3 is 'and'
 $4 is 'yet\ another'

待解决的问题

  • 是否存在无需使用eval的方法,用包含参数的字符串调用脚本?
  • 或者,是否有简便方法将该字符串转换为符合Bash解析逻辑的Array参数?(这样就可以通过数组元素展开调用脚本)

内容的提问来源于Stack Exchange,提问作者rellampec

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 01:50:30