【问题标题】:Is there any alternative to using eval in a shell script to achieve variable expansion在 shell 脚本中使用 eval 来实现变量扩展有什么替代方法吗
【发布时间】:2021-07-29 11:23:05
【问题描述】:

我有以下情况,其中 exec 和 eval 将以不同的方式处理作为参数传递的变量。 在这里,eval 似乎输出了一些预期的东西。

但是除了使用它还有其他选择吗?

$ cat arg.sh 
#!/bin/bash

eval ./argtest $*

$ ./arg.sh "arg1 'subarg1 subarg2'"
Args: 2
Arg1: arg1
Arg2: subarg1 subarg2

但同时,如果我使用 exec 而不是 eval 调用,单引号不会得到尊重。

$ ./arg.sh "arg1 'subarg1 subarg2'"
Args: 3
Arg1: arg1
Arg2: 'subarg1
Arg3: subarg2'

【问题讨论】:

  • 为什么不只是./argtest "$@"./arg.sh arg1 'subarg1 subarg2'
  • achieve variable expansion确定你想要变量扩展吗?您的示例显示了引号解析或解释,没有变量扩展......

标签: bash shell command-line-arguments


【解决方案1】:

应该这样做:

#!/bin/bash    
./argtest "$@"

正确传递未更改的参数。

然后做:

$ ./arg.sh arg1 'subarg1 subarg2'

就像你对任何其他命令所做的那样。

研究何时在 shell 中使用引号,$@ 位置参数扩展如何在引号中特别处理,研究 $*$@ 有何不同并研究分词。还要研究什么是变量扩展,它发生在什么上下文中,以及单引号与双引号有何不同。由于提到了 exec,请参阅bashfaq Eval command and security issues。记得用https://shellcheck.net 检查你的脚本。

除了在shell脚本中使用eval来实现变量扩展,还有什么替代方法

是的 - 使用 envsubst 进行变量扩展,这是一个工具。

#!/bin/bash
arg=$(VARIABLE=something envsubst '$VARIABLE' <<<"$1")
./argtest "$arg"

$ bash -x ./arg.sh 'string with **not-expanded** $VARIABLE'
+ ./argtest 'string with **not-expanded** something'

除了在shell脚本中使用eval来实现*单引号解析

是的 - 您可能会编写自己的解析器,可能在 awk 中,它将拆分字符串然后重新加载。一个非常粗略的例子:

#!/bin/bash
readfile -t args < <(sed "s/ *'\([^']*\)' */\n\1\n/; s/\n$//" <<<"$*")
./argtest "${args[@]}"

$ bash -x ./arg.sh  "arg1 'subarg1 subarg2'"
+ ./argtest 'arg1' 'subarg1 subarg2' 

【讨论】:

    【解决方案2】:

    使用 $*,shell 对参数应用分词,并将分词后的效果传递给eval,repsepcitvely exec。之后会发生什么,它们之间有所不同:

    exec 根据获得的第一个参数,将当前进程替换为一个新进程。比 in 将剩余的参数未修改传递给此进程。

    另一方面,

    eval 将参数连接到单个字符串(使用一个空格作为这些字符串之间的分隔符),然后将此结果字符串视为新命令这里应用了bash通常的扩展和分词机制,最后运行这个命令。

    机制完全不同,这并不奇怪,因为这些命令用于不同的目的。

    【讨论】:

      猜你喜欢
      • 2019-03-31
      • 1970-01-01
      • 2016-08-30
      • 1970-01-01
      • 1970-01-01
      • 2018-04-11
      • 1970-01-01
      • 1970-01-01
      • 2015-12-19
      相关资源
      最近更新 更多