| while read X "> | while read X Y X; do ... done"使用 因为在ba..."> | while read X " />
美文网首页
bash千万不要这样" | while read X

bash千万不要这样" | while read X

作者: CodingCode | 来源:发表于2020-08-10 05:18 被阅读0次

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

相关文章

网友评论

      本文标题:bash千万不要这样" | while read X

      本文链接:https://www.haomeiwen.com/subject/glkddktx.html