当我创建字符串时正在执行字符串中的 Bash 命令,而不是在我以后使用它时

Ric*_*cky 11 bash shell-script quoting

我对 shell 脚本比较陌生,但几乎完成了一个使用lftp 程序的脚本。我遇到问题的脚本部分是当我创建一长串命令(以 分隔;)时。

for var in something
do
    ...
    commands_to_run+="echo Result is `tail -n 1 $somefile`;"
done
Run Code Online (Sandbox Code Playgroud)

我注意到的是,该tail程序 - 用反引号包裹 - 在 for 循环迭代时正在运行,但在我稍后在脚本中调用命令字符串时不会运行。

不幸的是,$somefile 的内容在这个阶段还没有准备好进行检查。如何让命令在我需要时执行,而不是在我创建字符串时执行?

daB*_*mer 9

这个有点棘手。Hauke 提供的信息是正确的,这只是针对您的用例进行解析的问题。

最简单的方法是$()在转义 时使用语法,$这样变量定义就不会执行定义时由 括起来的命令$()。需要注意的是,最终结果必须eval在实际执行时由 shell重新评估(通过),以便执行嵌套命令。

看一个例子要容易得多,所以拿这个,它应该让你走上正确的轨道:

for((i=0;i<10;i++)); do 
  date +%s.%N  # Print a timestamp (in format seconds.nanoseconds)
  test="echo \$(date +%s.%N)" # Save a command to do the same
  sleep 1      # Sleep for a second
  eval "$test" # Evaluate the command saved in variable 'test'
  echo         # Print a new line before the next iteration
done
Run Code Online (Sandbox Code Playgroud)

以下是上述示例的示例输出(修剪为一次迭代):

1398832186.133661344
1398832187.139076728
Run Code Online (Sandbox Code Playgroud)

您会注意到每个循环的第二个时间戳在第一个之后大约一秒。相反,如果你不逃避执行相同的测试$test定义和拆卸eval,两个时间戳将几乎一致。

不要养成eval在大多数情况下使用的习惯,但这是我不知道避免它的好方法之一。希望这会有所帮助。祝你好运!


Hau*_*ing 6

有几个级别的引用。双引号 ( "...") 保护空格和几个特殊字符 ( ~, &, |, ;, ...) 但不阻止参数扩展和命令替换。

您需要'在“危险”字符前使用单引号 ( ) 或反斜杠。

一般来说:您应该考虑使用$(tail ...)而不是反引号。反引号是较旧的标准,但我们谈论的是太旧了,$()不会对大多数人造成问题。新版本更易于阅读并且可以嵌套。更不用说 sx 上的格式问题了...