while 循环和此处文档 - 什么时候会发生什么?

while 循环和此处文档 - 什么时候会发生什么?

我有这个 while 循环和此处文档组合,我在 Bash 4.3.48(1) 中运行,但我根本不理解它的逻辑。

while read file; do source ~/unwe/"$file"
done <<-EOF
    x.sh
    y.sh
EOF

我的问题由以下部分组成:

  1. 这里做什么read(我总是用来read声明一个变量并为其赋值交互地,但我错过了它在这里应该做什么)。

  2. 是什么意思while read?这里的概念从何while而来?

  3. 如果此处文档本身出现循环,它是如何受到循环影响的?我的意思是,它出现在 后面done,而不是循环内部,那么这两个结构之间的实际关联是什么?

  4. 为什么会失败?

    while read file; do source ~/unwe/"$file" done <<-EOF
        x.sh
        y.sh
    EOF
    

    我的意思是,done是... 那么,如果与循环位于同一行,done为什么很重要呢?如果我没记错的话,我确实遇到过一个循环是单行但仍然有效的done <<-EOF情况。for

答案1

  1. read命令从其标准输入流读取并将读取的内容分配给变量file(比这更复杂一点,请参阅这里进行长时间的讨论)。标准输入流来自here-document,重定向到after 循环中done。如果没有给出数据从任何地方,它将以交互方式从终端读取。但在这种情况下,shell 已安排将其输入流连接到此处文档。

  2. while read将导致循环迭代,直到read命令返回非零退出状态。如果存在任何错误,或者(最常见)当没有更多数据可供读取(其输入流处于文件结束状态)时,就会发生这种情况。

    约定是任何希望向调用 shell 发出错误或“假”或“否”信号的实用程序都通过返回非零退出状态来实现。零退出状态表示“真”或“是”或“无错误”。您希望检查此状态吗?$?(仅来自最后执行的实用程序)。退出状态可以用在if语句和while循环中或任何需要测试的地方。例如

    if grep -q 'pattern' file; then ...; fi
    
  3. 这里的文档是重定向的一种形式。在这种情况下,它是重定向到循环中。循环内的任何内容都可以从中读取,但在本例中只有命令可以read读取。请阅读此处的文档。如果输入来自普通文件,则最后一行将是

    done <filename
    

    将循环视为一个命令可能会使这一点更加直观:

    while ...; do ...; done <filename
    

    这是一种情况

    somecommand <filename
    

    一些 shell 还支持“here-strings” <<<"string"

    cat <<<"This is the here-string"
    

    大卫·福斯特指出如果两个脚本中的任何一个从标准输入x.sh读取y.sh,而没有明确给出从文件或其他地方读取的数据,则读取的数据实际上来自此处文档。

    如果 ax.sh只包含read a,这将使变量a包含字符串y.sh,并且y.sh脚本将永远不会运行。这是因为标准输入被重定向为全部循环中的命令while(也由任何调用的脚本或命令“继承”),第二行在循环可以读取它x.sh之前被“消耗”。whileread

    如果这种行为是不受欢迎的,可以避免,但这有点棘手

  4. 它失败是因为 之前没有;换行符done。如果前面没有;或换行符done,该单词done将被视为 的参数source,并且循环将另外无法正确关闭(这是语法错误)。

    几乎正确的是,any;可以被换行符替换(至少当它是命令分隔符时)。它标志着命令的结束,就像|&&&||(可能还有其他我已经忘记的)一样。

答案2

您实际上是创建一个对象作为文档,然后将其重定向回 while 循环,逐行读取它,直到没有剩余行,并在该行上执行源命令。

另一种执行方式如下:

假设线路

x.sh
y.sh

在一个名为:

input.txt

我们可以执行

cat input.txt | while read file
   do source ~/unwe/"$file"
done

这里的文档使事情更具交互性,但上面的示例可能会让您更好地理解它。

相关内容