我对 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 上的格式问题了……