为什么这个循环是针对空集执行的?

为什么这个循环是针对空集执行的?

创建一个空目录,然后运行以下代码:

find /empty_directory -mindepth 1 -maxdepth 1 -type d |
while read dir;
do
    echo "Simple find: $dir"
done

printf '%s\n' '-----'                   # Safer than    echo -----

while read dir;
do
    echo "HereDoc find: $dir"
done <<< "$(find /empty_directory -mindepth 1 -maxdepth 1 -type d)"

这是输出:

-----
HereDoc find: 

换句话说,第二个循环使用空变量执行一次。

为什么会这样?如何才能使第二个循环正常运行,并且在没有找到要循环的目录时不运行?

答案1

发生了什么?

我知道您正在尝试解决特定问题,但调试的首要规则之一是简化场景。如果我们这样做

$ sleep 1 | read x
$ echo "$?"
1

$ read x <<< $(sleep 1)
$ echo "$?"
0

我们看到read来自空管道的 a 失败,但 read来自 null 字符串的 a 成功(读取空值)。这就是你所看到的。

它的拼写是重击(1):

这里是字符串

    Here 文档的一个变体,格式为:

        [n]<<<word

    word进行波形符扩展、参数和变量扩展、命令替换、算术扩展和引号删除。不执行路径名扩展和分词。结果作为单个字符串提供,附加换行符, 到其标准输入(或文件描述符)上的命令n 如果n已指定)。

      (强调已添加)

Bash 将此处的 null 字符串转换为空行,而不是 EOF。

如何修复它?

显而易见的是——修改循环逻辑:

读取目录时  && [“$dir”!=“”]
    echo "HereDoc 查找:$dir"
完成 <<< "$(find /empty_directory -min深度 1 -max深度 1 -type d)"
如果读取到空行,则终止循环。

同样明显的是——修改逻辑循环:

读取目录时
    如果[“$dir”=“”];然后继续;菲
    echo "HereDoc 查找:$dir"
完成 <<< "$(find /empty_directory -min深度 1 -max深度 1 -type d)"
这会忽略空行(但不会终止循环)。

也许更好——修改重定向:

读取目录时
    echo "HereDoc 查找:$dir"
完毕<<(查找 /empty_directory -min深度 1 -max深度 1 -类型 d)
通过使用进程替换 ( ) 和简单重定向 (<(command)<) 而不是命令替换 ( ) 和此处的字符串 ($(command)<<<),您可以阻止 Bash 添加换行符。

PS 请注意,您不需要;像使用 那样在行尾添加分号 () while read dir

相关内容