为什么 exit 命令不退出嵌套的 while 循环?

为什么 exit 命令不退出嵌套的 while 循环?

我有以下脚本。它从 passwd 打印所有第一个字符到控制台,但我的期望是只获得一个字符,然后程序终止。

#!/bin/sh 

cat /etc/passwd |
while read -r line
do
    echo ${line} |
        grep -o . |
        while read char
        do
            echo ${char}   
            exit 1       
        done
done

实际输出:

r
b
d
a
(etc)

预期输出:

r

答案1

大多数类似 Bourne 的 shell,除了zshksh子 shell 中运行管道的每个部分。假设您不使用zshor ksh,那么在您的脚本中, pipiline 的最后一部分在子 shell 中运行,因此exit退出该子 shell 而不是当前 shell。

zsh您将在或中得到所需的输出ksh

无论如何,这些代码有很多缺陷:


如果您想要的只是获取文件中的第一个字符:

dd bs=1 count=1 if=/etc/passwd 2>/dev/null

或使用 GNU dd

dd status=none bs=1 count=1 if=/etc/passwd

它仅适用于 ASCII 字符。对于多字节字符:

LC_ALL=en_US.utf8 awk '{print substr($0,1,1);exit}'

更改LC_ALL为您的文本所属的区域设置。

答案2

管道创建子壳。 shell 内置命令exit终止 shell。导致您的情况出现意外行为:

> exit | exit | echo wow
wow

我建议看看管道中的部分man bash。还看看help exit

相关内容