我在从while循环内部更新shell脚本中的变量值时遇到问题。它可以使用以下代码进行模拟:
printf "aaa\nbbb\n" | \ while read x ; do y=$x echo "INSIDE: $y" done echo "OUTSIDE: $y"
输出:
INSIDE: aaa INSIDE: bbb OUTSIDE:
这里printf命令只显示两行,while-read循环逐行读取,更新某个变量,但是一旦控件退出循环,变量的值就会丢失。
我猜这个问题与'pipe-while-read'语句导致shell在子进程中执行循环体这一事实有关,该子进程无法更新主循环中的shell变量。
如果我将前两行代码重写为
for x in `printf "aaa\nbbb\n" ` ; do
输出:
INSIDE: aaa INSIDE: bbb OUTSIDE: bbb
这可能是一种解决方法,但不适用于我的情况,因为实际上我没有'aaa'和'bbb',而是更复杂的字符串,包括空格等。
知道如何解决这个问题,即:在循环中逐行读取命令输出并能够更新shell变量吗?
感谢。
答案 0 :(得分:1)
您可以使用process substitution来取消管道输入:
while read x ; do
y=$x
echo "INSIDE: $y"
done < <(printf "aaa\nbbb\n")
echo "OUTSIDE: $y"
或者,如果您的输入位于文件中,则可以将其重定向到while:
while read x ; do
y=$x
echo "INSIDE: $y"
done < file
echo "OUTSIDE: $y"
答案 1 :(得分:1)
摘自man bash
:
管道中的每个命令都作为一个单独的进程执行(即在子shell中)。
并且Subshell无法更改Parent中的变量。
可能的解决方案之一是:
IFS='\n'
while read x ; do
y=${x}
echo "INSIDE: ${y}"
done <<EOT
aaa
bbb
EOT
echo "OUTSIDE: ${y}"
或者如果输入是文件:
IFS='\n'
while read x ; do
y=${x}
echo "INSIDE: ${y}"
done < /path/to/file
echo "OUTSIDE: ${y}"
一次读取一行,空格没有任何问题。