unset myVariable i;
while [ -z "$i" ]; do
read myVariable;
echo "myVariable : '$myVariable'";
i=foo;
done;
echo "myVariable : '$myVariable'"
(unset
是否允许重播命令)
按任意键 + ENTER,您将获得:
myVariable : '[what you typed]'
myVariable : '[what you typed]'
的值myVariable
存在于while
循环之外。现在尝试:
tmpFile=$(mktemp);
echo -e 'foo\nbar\nbaz' >> "$tmpFile"
while read myVariable; do
otherVariable=whatever;
echo "myVariable : '$myVariable', otherVariable : '$otherVariable'";
done < "$tmpFile";
echo "myVariable : '$myVariable', otherVariable : '$otherVariable'";
rm "$tmpFile"
你会得到 :
myVariable : 'foo', otherVariable : 'whatever'
myVariable : 'bar', otherVariable : 'whatever'
myVariable : 'baz', otherVariable : 'whatever'
myVariable : '', otherVariable : 'whatever'
myVariable
离开循环时会丢失的值。
为什么会有不同的行为?有没有我不知道的范围技巧?
注意:运行 GNU bash,版本 4.4.12(1)-release (x86_64-pc-linux-gnu)
不,
myVariable
它具有从 last 获得的价值read
。脚本从文件中读取,直到到达最后一个换行符之后的位置。之后,最终read
调用从文件中什么也得不到,相应地设置myVariable
为空字符串,并以假值退出,因为它没有看到分隔符(换行符)。然后循环结束。read
如果在最后一个换行符之后有不完整的行,您可以从最终获得一个非空值:或用于
while read a || [ "$a" ]; do ...
处理循环体内的最后一行片段。在这种情况下,
done < "$tmpFile"
重定向会强制 bash 生成一个子 shell(如管道)。引用自Stack Overflow 上的bash 变量范围。
您的第二个示例使用
while
具有重定向输入的循环。它读取 using
< "$tmpFile"
并且许多 shell 为这种情况创建了一个子 shell。您可以尝试使用ksh93
.ksh93
在这种情况下不会创建子外壳。在您的具体情况下,原因完全不同:
在第一个示例中,您从输入中读取了一行
在第二个示例中,您阅读直到
EOF
到达该
read
命令读取输入,然后将输入拆分为IFS
字符,然后将单词分配给 的变量参数read
。如果作为命令参数的单词多于变量
read
,则最后一个变量将连接其余单词。如果单词少于变量,则为其他变量分配一个空值。
自从您点击
EOF
后,您没有读取任何单词,但有一个或多个变量作为read
. 这会导致所有变量都分配一个空值。所以发生了一些你没想到
EOF
的事情:导致while
循环被终止,你看不到循环echo
内的命令,但在这种情况下while
只有循环之后的最终echo
命令。while
EOF
这个 final
echo
现在打印从 hit 中清除的变量内容EOF
。