Bash 在循环内设置一个全局变量并保留其值——或者处理虚拟变量
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9012841/
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 setting a global variable inside a loop and retaining its value -- Or process substituion for dummies
提问by Hassan Syed
I'm a C/C++ programmer and quite stupid in general (or at least the way bash does things it makes me feel confused). I can't wrap my head around process substitution.
我是一名 C/C++ 程序员,总的来说很愚蠢(或者至少 bash 做事的方式让我感到困惑)。我无法理解进程替换。
I need to define a global boolean, set it somewhere in a loop, and make use of it in global scope. Could someone please explain in the simplest way possible how to adapt the code below to allow me to achieve my use case, simple enough so that I don't have to contort my brain again tomorrow to try and grasp process substitution .
我需要定义一个全局布尔值,将其设置在循环中的某个位置,并在全局范围内使用它。有人可以用最简单的方式解释如何调整下面的代码以让我实现我的用例,足够简单以至于我明天不必再次扭曲我的大脑来尝试掌握过程替换。
# DEFINE HERE
for i in `seq 0 ${DAEMON_COUNT}`;
do
if [ ! -d "data$i" ]; then
# SET HERE
echo "data$i does not exist. Creating...";
mkdir data$i
fi
done
# TEST AND USE HERE
to be honest, I don't think bash is up to the task.... the next block looks like this.
老实说,我不认为 bash 能胜任这项任务......下一个块看起来像这样。
echo "-------------------------------------------------------------------------------"
echo "checking the state of potentially running daemons"
for i in `seq 0 ${DAEMON_COUNT}`;
do
if [ ! -e "data$i/mongod.lock" ] ; then
echo "[no lock file] mongod process $i does not exist"
else
echo "[lock file exists] process $i lock file exists "
I_PID=`cat data$i/mongod.lock`
if [ ! ${I_PID} ]; then
echo " [GOOD] lock pid empty"
elif [ "`ps -p ${I_PID} | grep ${I_PID}`" ]; then
echo " [GOOD] data1 pid: ${I_PID} running"
else
echo "[PROBABLY FATAL] data1 pid: ${I_PID} not running."
fi
fi
done
echo "-------------------------------------------------------------------------------"
What I now need is a global array of structs so that I can loop over them and take conditional action to initialize my daemons correctly :/.
我现在需要的是一个全局结构数组,以便我可以遍历它们并采取条件操作来正确初始化我的守护进程:/。
Might just use libc and do this stuff in lua, the only reason I hold back is having to install rocks, I don't like ad-hoc code repositories vomiting whatever they want onto my machine :D
可能只使用 libc 并在 lua 中做这些事情,我阻止的唯一原因是必须安装岩石,我不喜欢临时代码存储库在我的机器上吐出他们想要的任何东西:D
回答by Adam Zalcman
The important thing to understand is this: child process is born with its own environment and cannot affect the variables of its parent. If you set a variable in a child process, then the value of the variable in the parent is not affected. These are actually two different variables which just happen to have the same name.
需要理解的重要一点是:子进程天生就有自己的环境,不能影响其父进程的变量。如果在子进程中设置变量,那么父进程中变量的值不受影响。这些实际上是两个不同的变量,只是碰巧具有相同的名称。
The second thing to understand is when bash runs a command as a child process. There are two cases relevant to the question:
要了解的第二件事是 bash 何时将命令作为子进程运行。有两种情况与问题相关:
- Each process connected by a pipe
|is a child of the current shell. - Running a single builtin command with a redirection (e.g.
<) will not spawn a child process.
- 每个由管道连接的进程
|都是当前 shell 的子进程。 - 运行带有重定向的单个内置命令(例如
<)不会产生子进程。
Here is a simple session which demonstrates these ideas:
这是一个演示这些想法的简单会话:
$ somevar=initial
$ echo test1 | read somevar
$ echo $somevar
initial
$ read somevar < <(echo test2)
$ echo $somevar
test2
The first readis a child process and therefore somevarin the main shell does not change. The second readis executed by the main shell itself and hence somevaris updated.
第一个read是子进程,因此somevar在主 shell 中不会改变。第二个read由主 shell 本身执行,因此somevar被更新。
This means that your code will work as you expect unless you add a pipe in front of or after the forloop, i.e. this works as you want it to:
这意味着除非您在for循环之前或之后添加管道,否则您的代码将按预期工作,即按您的意愿工作:
# DEFINE HERE
SOMEVAR=0
DAEMON_COUNT=10
for i in `seq 0 ${DAEMON_COUNT}`;
do
if [ ! -d "data$i" ]; then
# SET HERE
SOMEVAR=10
echo "data$i does not exist. Creating...";
mkdir data$i
fi
done
# TEST AND USE HERE
echo ${SOMEVAR} # This displays 10
回答by clime
I might have misundestood but...
我可能误会了但是...
bool=false;
for i in `seq 0 ${DAEMON_COUNT}`;
do
if [ ! -d "data$i" ]; then
bool=true;
echo "data$i does not exist. Creating...";
mkdir data$i
fi
done
if [ $bool = true ]; then
...
fi
Is this what you want?
这是你想要的吗?

