bash千万不要这样"<cmd> | while read X Y X; do ... done"使用
因为在bash里面”|"后命令是在一个新的shell里面运行的,即“|”前后不在一个进程里面,所以如果在while循环里面使用了变量之类的赋值,就会无效。
举个例子:
#!/bin/bash
VAR=AAA
echo ${VAR}
echo "Hello World" | tr ' ' '\n' | while read WORD; do
VAR=BBB
echo ${VAR}
done
echo ${VAR}
运行结果:
AAA
BBB
BBB
AAA
看到在while循环内尽管已经把VAR置成了BBB,但是在循环退出后,VAR的值还是回退到AAA,也就是循环内变量赋值无效。
为什么呢,因为while循环实在一个独立的进程空间里面运行的,在那个进程内把VAR改成了BBB,但是并不影响在外面主进程的空间。
我们把PID打出来看看:
VAR=AAA
echo ${VAR}
echo PID=$$
echo "Hello World" | tr ' ' '\n' | while read WORD; do
VAR=BBB
echo ${VAR}
echo PID=$$
done
echo ${VAR}
echo PID=$$
运行:
AAA
PID=87654
BBB
PID=87654
BBB
PID=87654
AAA
PID=87654
貌似PID也一样啊,不是吗?
不是的,因为打印PID的用法错误了,"$$"在脚本启动的时候就解析完了,全部替换成了当前进程的PID所以都一样;我们改一下:
#!/bin/bash
VAR=AAA
echo ${VAR}
cut -d' ' -f4 < /proc/self/stat
echo "Hello World" | tr ' ' '\n' | while read WORD; do
VAR=BBB
echo ${VAR}
cut -d' ' -f4 < /proc/self/stat
done
echo ${VAR}
cut -d' ' -f4 < /proc/self/stat
在运行:
AAA
87896
BBB
87900
BBB
87900
AAA
87896
这里就可以看出while循环内的PID和循环外的PID是不一样的。
那应该怎么用呢:
答:
while read X, Y, X; do
...
done < <(<cmd>)
例:
#!/bin/bash
VAR=AAA
echo ${VAR}
cut -d' ' -f4 < /proc/self/stat
while read WORD; do
VAR=BBB
echo ${VAR}
cut -d' ' -f4 < /proc/self/stat
done < <(echo "Hello World" | tr ' ' '\n')
echo ${VAR}
cut -d' ' -f4 < /proc/self/stat
得到运行结果:
AAA
89047
BBB
89047
BBB
89047
BBB
89047
网友评论