use*_*970 8 text-processing control-flow here-document variable read
我有这个 while 循环和 here-document 组合,我在 Bash 4.3.48(1) 中运行,我根本不明白它的逻辑。
while read file; do source ~/unwe/"$file"
done <<-EOF
x.sh
y.sh
EOF
Run Code Online (Sandbox Code Playgroud)
我的问题由以下部分组成:
read这里做什么(我总是read用来声明一个变量并以交互方式分配它的值,但我错过了它应该在这里做什么)。
是什么意思while read?while进来的概念从哪里来?
如果 here-document 本身出现在循环之后,它甚至如何受到循环的影响?我的意思是,它出现在 之后done,而不是在循环内部,那么这两个结构之间的实际关联是什么?
为什么这会失败?
while read file; do source ~/unwe/"$file" done <<-EOF
x.sh
y.sh
EOF
Run Code Online (Sandbox Code Playgroud)
我的意思是,done是done...那么为什么done <<-EOF与循环在同一行上很重要?如果我没记错的话,我确实遇到过这样一种情况,其中for循环是单行的并且仍然有效。
Kus*_*nda 13
该read命令从其标准输入流中读取并将读取的内容分配给变量file(它比这更复杂,请参阅此处的详细讨论)。标准输入流来自 here-document 之后重定向到循环中done。如果没有从任何地方提供数据,它将以交互方式从终端读取。但在这种情况下,shell 已安排将其输入流连接到 here-document。
while read将导致循环迭代,直到read命令返回非零退出状态。如果有任何错误,或者(最常见)没有更多数据可供读取(其输入流处于文件结束状态),就会发生这种情况。
约定是,任何希望向调用 shell 发出错误或“假”或“否”信号的实用程序都通过返回非零退出状态来实现。零退出状态表示“真”或“是”或“无错误”。此状态,您是否希望检查它,在$?(仅从上次执行的实用程序中)可用。退出状态可用于if语句和while循环或任何需要测试的地方。例如
if grep -q 'pattern' file; then ...; fi
Run Code Online (Sandbox Code Playgroud)here-document 是重定向的一种形式。在这种情况下,它是重定向到循环中。循环内的任何内容都可以从中读取,但在这种情况下,只有read命令才能读取。请仔细阅读此处的文档。如果输入来自一个普通文件,最后一行应该是
done <filename
Run Code Online (Sandbox Code Playgroud)
将循环视为一个命令可能会使这更直观:
while ...; do ...; done <filename
Run Code Online (Sandbox Code Playgroud)
这是一种情况
somecommand <filename
Run Code Online (Sandbox Code Playgroud)
一些 shell 还支持“here-strings” <<<"string":
cat <<<"This is the here-string"
Run Code Online (Sandbox Code Playgroud)
DavidFoerster指出,如果任何两个脚本x.sh,并y.sh从标准输入读取,但没有明确报错数据从文件或从其他地方读取,读取的数据实际上会从这里文档。
如果 ax.sh只包含read a,这将使变量a包含字符串y.sh,并且y.sh脚本永远不会运行。这是因为标准输入被重定向到循环中的所有命令while(并且还被任何调用的脚本或命令“继承”),并且第二行在循环可以读取x.sh之前被“消耗” 。whileread
如果这种行为是不需要的,则可以避免,但有点棘手。
它失败是因为;之前没有或换行符done。;之前没有或换行done,单词done将被视为 的参数source,并且循环也不会正确关闭(这是一个语法错误)。
any 几乎;可以用换行符替换(至少当它是命令分隔符时)。它标志着一个命令的结尾,一样|,&,&&和||(也可能是别人,我已经忘记了)。