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

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

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

for var in something
do
    ...
    commands_to_run+="echo Result is `tail -n 1 $somefile`;"
done

我注意到的是,tail程序(用反引号括起来)是在 for 循环迭代时运行的,而不是在我稍后在脚本中调用命令字符串时运行的。

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

答案1

这个有点棘手。 Hauke 提供的信息是正确的,只需根据您的用例对其进行解析即可。

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

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

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

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

1398832186.133661344
1398832187.139076728

您会注意到每个循环的第二个时间戳大约在第一个时间戳之后一秒。相反,如果您执行相同的测试而不转义定义$中的test并删除eval,则两个时间戳将几乎匹配。

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

答案2

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

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

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

相关内容