具有多个命令和可重入的 BASH 变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1121189/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
BASH Variables with multiple commands and reentrant
提问by Eric
I have a bash script that sources contents from another file. The contents of the other file are commands I would like to execute and compare the return value. Some of the commands are have multiple commands separated by either a semicolon (;) or by ampersands (&&) and I can't seem to make this work. To work on this, I created some test scripts as shown:
我有一个 bash 脚本,它从另一个文件中获取内容。另一个文件的内容是我想执行和比较返回值的命令。有些命令有多个命令,由分号 (;) 或与号 (&&) 分隔,我似乎无法完成这项工作。为了解决这个问题,我创建了一些测试脚本,如下所示:
test.conf is the file being sourced by test
test.conf 是测试来源的文件
Example-1 (this works), My output is 2 seconds in difference
示例 1(这有效),我的输出相差 2 秒
test.conf
测试配置文件
CMD[1]="date"
test.sh
测试文件
. test.conf
i=2
echo "$(${CMD[$i]})"
sleep 2
echo "$(${CMD[$i]})"
Example-2 (this does not work) test.conf (same script as above)
示例 2(这不起作用) test.conf(与上面相同的脚本)
CMD[1]="date;date"
Example-3 (tried this, it does not work either) test.conf (same script as above)
Example-3(试过这个,它也不起作用)test.conf(与上面相同的脚本)
CMD[1]="date && date"
I don't want my variable, CMD, to be inside tick marks because then, the commands would be executed at time of invocation of the source and I see no way of re-evaluating the variable.
我不希望我的变量 CMD 位于刻度线内,因为这样,命令将在调用源时执行,我看不到重新评估变量的方法。
This script essentially calls CMD on pass-1 to check something, if on pass-1 I get a false reading, I do some work in the script to correct the false reading and re-execute & re-evaluate the output of CMD; pass-2.
该脚本本质上在 pass-1 上调用 CMD 来检查某些内容,如果在 pass-1 上我得到错误读数,我会在脚本中做一些工作来纠正错误读数并重新执行和重新评估 CMD 的输出;通过-2。
Here is an example. Here I'm checking to see if SSHD is running. If it's not running when I evaluate CMD[1] on pass-1, I will start it and re-evaluate CMD[1] again.
这是一个例子。在这里,我正在检查 SSHD 是否正在运行。如果我在 pass-1 评估 CMD[1] 时它没有运行,我将启动它并再次重新评估 CMD[1]。
test.conf
测试配置文件
CMD[1]=`pgrep -u root -d , sshd 1>/dev/null; echo $?`
So if I modify this for my test script, then test.conf becomes: NOTE: Tick marks are not showing up but it's the key below the ~ mark on my keyboard.
因此,如果我为我的测试脚本修改它,那么 test.conf 将变为: 注意:没有显示刻度线,但它是我键盘上 ~ 标记下方的键。
CMD[1]=`date;date` or `date && date`
My script looks like this (to handle the tick marks)
我的脚本看起来像这样(处理刻度线)
. test.conf
i=2
echo "${CMD[$i]}"
sleep 2
echo "${CMD[$i]}"
I get the same date/time printed twice despite the 2 second delay. As such, CMD is not getting re-evaluate.
尽管延迟了 2 秒,但我还是打印了两次相同的日期/时间。因此,CMD 不会被重新评估。
采纳答案by Paused until further notice.
First of all, you should never use backticks unless you need to be compatible with an old shell that doesn't support $()- and only then.
首先,除非您需要与不支持的旧外壳兼容,否则永远不应使用反引号$()-只有这样。
Secondly, I don't understand why you're setting CMD[1]but then calling CMD[$i]with iset to 2.
其次,我不明白你为什么要设置CMD[1],然后CMD[$i]用iset to调用2。
Anyway, this is one way (and it's similar to part of Barry's answer):
无论如何,这是一种方式(它类似于巴里的部分答案):
CMD[1]='$(date;date)' # no backticks (remember - they carry Lime disease)
eval echo "${CMD[1]}" # or $i instead of 1
回答by Barry Kelly
From the couple of lines of your question, I would have expected some approach like this:
从你的问题的几行来看,我本来希望有这样的方法:
#!/bin/bash
while read -r line; do
# munge $line
if eval "$line"; then
# success
else
# fail
fi
done
Where you have backticks in the source, you'll have to escape them to avoid evaluating them too early. Also, backticks aren't the only way to evaluate code - there is eval, as shown above. Maybe it's evalthat you were looking for?
如果源代码中有反引号,则必须将它们转义以避免过早评估它们。此外,反引号不是评估代码的唯一方法 - 有eval,如上所示。也许这eval就是你要找的?
For example, this line:
例如,这一行:
CMD[1]=`pgrep -u root -d , sshd 1>/dev/null; echo $?`
Ought probably look more like this:
应该看起来更像这样:
CMD[1]='`pgrep -u root -d , sshd 1>/dev/null; echo $?`'

