bash:读取命令不支持 IFS

bash:读取命令不支持 IFS

从该命令的 bash 手册页read

从标准输入或从作为 -u 选项的参数提供的文件描述符 fd 读取一行,按照上面的单词拆分中所述拆分为单词,并将第一个单词分配给名字,...

现在我尝试了以下方法:

IFS=,
echo ' a b,c d'|read -n 4 x y
echo ".$x. .$y."

我预计输出是

. a b. .c d.

因为由于更改,分词应该发生在逗号而不是空格处,但实际输出是

.a. ..

这让我很困惑。看起来.a.分词仍然是在空格处完成的,但至少y应该设置为b,而不是空的。

我不禁觉得我误解了手册页中有关该read命令的解释。

顺便说一句,我正在使用 bash 4.4.12。

答案1

它工作得很好:

$ IFS=,; echo ' a b,c d' | { read x y; declare -p x y;}
declare -- x=" a b"
declare -- y="c d"

笔记

  1. 因为它在管道中,所以该read语句位于子 shell 中。变量x和 的y范围仅限于该子 shell。在上面,我们添加了花括号,以便该declare语句与该语句位于同一子 shell 中read。这样,声明输出就会显示读取的 x 和 y 值。

    如果我们删除大括号,则该declare语句不再位于同一子 shell 中,并且x和的值y也不会保留。观察:

    $ x=hot; y=cold; IFS=,; echo ' a b,c d' | read -n 4 x y; declare -p x y
    declare -- x="hot"
    declare -- y="cold"
    
  2. 为了避免子shell限制,我们可以使用here-string:

    $ IFS=,; read x y <<<' a b,c d'; declare -p x y
    declare -- x=" a b"
    declare -- y="c d"
    

    使用here-string,语句位于主 shell 中,并且和read的值不会丢失。xy

  3. -n 4限制read为 4 个字符。这可能不是你想要的。观察:

    $ IFS=,; echo ' a b,c d' | { read -n 4 x y; declare -p x y;}
    declare -- x=" a b"
    declare -- y=""
    

    这里, x占据了全部 4 个字符(空格也算作字符),没有读取任何字符y

  4. 作为佩萨,也可以只为执行一个命令而在本地分配 shell 变量。由于对 IFS 的更改可能会在后续命令中导致不必要的副作用,因此这是一个好主意。因此:

    $ IFS=, read x y <<<' a b,c d'; declare -p x y
    declare -- x=" a b"
    declare -- y="c d"
    

    上述命令运行后,IFS返回到之前的值。

相关内容