我有这个 while 循环和此处文档组合,我在 Bash 4.3.48(1) 中运行,但我根本不理解它的逻辑。
while read file; do source ~/unwe/"$file"
done <<-EOF
x.sh
y.sh
EOF
我的问题由以下部分组成:
这里做什么
read
(我总是用来read
声明一个变量并为其赋值交互地,但我错过了它在这里应该做什么)。是什么意思
while read
?这里的概念从何while
而来?如果此处文档本身出现后循环,它是如何受到循环影响的?我的意思是,它出现在 后面
done
,而不是循环内部,那么这两个结构之间的实际关联是什么?为什么会失败?
while read file; do source ~/unwe/"$file" done <<-EOF x.sh y.sh EOF
我的意思是,
done
是... 那么,如果与循环位于同一行,done
为什么很重要呢?如果我没记错的话,我确实遇到过一个循环是单行但仍然有效的done <<-EOF
情况。for
答案1
该
read
命令从其标准输入流读取并将读取的内容分配给变量file
(比这更复杂一点,请参阅这里进行长时间的讨论)。标准输入流来自here-document,重定向到after 循环中done
。如果没有给出数据从任何地方,它将以交互方式从终端读取。但在这种情况下,shell 已安排将其输入流连接到此处文档。while read
将导致循环迭代,直到read
命令返回非零退出状态。如果存在任何错误,或者(最常见)当没有更多数据可供读取(其输入流处于文件结束状态)时,就会发生这种情况。约定是任何希望向调用 shell 发出错误或“假”或“否”信号的实用程序都通过返回非零退出状态来实现。零退出状态表示“真”或“是”或“无错误”。您希望检查此状态吗?
$?
(仅来自最后执行的实用程序)。退出状态可以用在if
语句和while
循环中或任何需要测试的地方。例如if grep -q 'pattern' file; then ...; fi
这里的文档是重定向的一种形式。在这种情况下,它是重定向到循环中。循环内的任何内容都可以从中读取,但在本例中只有命令可以
read
读取。请阅读此处的文档。如果输入来自普通文件,则最后一行将是done <filename
将循环视为一个命令可能会使这一点更加直观:
while ...; do ...; done <filename
这是一种情况
somecommand <filename
一些 shell 还支持“here-strings”
<<<"string"
:cat <<<"This is the here-string"
大卫·福斯特指出如果两个脚本中的任何一个从标准输入
x.sh
读取y.sh
,而没有明确给出从文件或其他地方读取的数据,则读取的数据实际上来自此处文档。如果 a
x.sh
只包含read a
,这将使变量a
包含字符串y.sh
,并且y.sh
脚本将永远不会运行。这是因为标准输入被重定向为全部循环中的命令while
(也由任何调用的脚本或命令“继承”),第二行在循环可以读取它x.sh
之前被“消耗”。while
read
如果这种行为是不受欢迎的,可以避免,但这有点棘手。
它失败是因为 之前没有
;
换行符done
。如果前面没有;
或换行符done
,该单词done
将被视为 的参数source
,并且循环将另外无法正确关闭(这是语法错误)。几乎正确的是,any
;
可以被换行符替换(至少当它是命令分隔符时)。它标志着命令的结束,就像|
、&
、&&
和||
(可能还有其他我已经忘记的)一样。
答案2
您实际上是创建一个对象作为文档,然后将其重定向回 while 循环,逐行读取它,直到没有剩余行,并在该行上执行源命令。
另一种执行方式如下:
假设线路
x.sh
y.sh
在一个名为:
input.txt
我们可以执行
cat input.txt | while read file
do source ~/unwe/"$file"
done
这里的文档使事情更具交互性,但上面的示例可能会让您更好地理解它。