为 for 循环设置 IFS 时的奇怪 bash 行为

Nuc*_*ear 2 bash for

我有一个值列表,用 ':' 分隔,我想一一处理它们。

当分隔符为空格时,没有问题:

nuclear@korhal:~$ for a in 720 500 560 130; do echo $a; done
720
500
560
130
Run Code Online (Sandbox Code Playgroud)

但是在将 IFS(内部字段分隔符)设置为 : 后,奇怪的事情开始发生:

nuclear@korhal:~$ IFS=":" for a in 720:500:560:130; do echo $a; done;
bash: syntax error near unexpected token `do'
Run Code Online (Sandbox Code Playgroud)

如果我跳过所有分号,则在设置 IFS 时:

nuclear@korhal:~$ IFS=":" for a in 720:500:560:130 do echo $a done;
Command 'for' not found, did you mean:
  command 'vor' from deb vor (0.5.8-1)
  command 'fop' from deb fop (1:2.5-1)
  command 'tor' from deb tor (0.4.4.5-1)
  command 'forw' from deb mailutils-mh (1:3.9-3.2)
  command 'forw' from deb mmh (0.4-2)
  command 'forw' from deb nmh (1.7.1-7)
  command 'sor' from deb pccts (1.33MR33-6build1)
  command 'form' from deb form (4.2.1+git20200217-1)
  command 'fox' from deb objcryst-fox (1.9.6.0-2.2)
  command 'fort' from deb fort-validator (1.4.0-1)
  command 'oor' from deb openoverlayrouter (1.3.0+ds1-3)
Try: sudo apt install <deb name>
Run Code Online (Sandbox Code Playgroud)

Bash 根本无法识别 for 命令。如果在这种情况下没有设置 IFS,它将显示提示,因为它需要更多输出(正常行为)

当 IFS 设置为自定义字符时会发生什么?为什么 for 循环不适用于它?

我使用的是 Kubuntu 20.10 Bash 版本 5.0.17

ilk*_*chu 8

分配后无法识别关键字。所以,forinIFS=blah for ...只是运行一个名为 的常规命令for,如果你有一个:

$ cat > ./for
#!/bin/sh  
echo script for
$ chmod +x ./for 
$ PATH=$PATH:.
$ for x in a b c
> ^C
$ foo=bar for x in a b c
script for
Run Code Online (Sandbox Code Playgroud)

但是因为 Bash 在运行之前会解析整个输入行,所以关键字do会在此之前导致语法错误。

这类似于用重定向代替分配: 我可以在复合命令之前指定重定向输入吗?另请参阅为什么不能反转 while 循环的输入重定向运算符的顺序?有关如何定义语法的详细信息。

另请参阅:如何在 bash for 循环中使用临时环境变量?

我的 Zsh 更严格:

$ zsh -c 'foo=bar for x in a b c'
zsh:1: parse error near `for'
Run Code Online (Sandbox Code Playgroud)

但是 Zsh 确实允许在复合命令之前重定向。这将三行输出到test.txt

$ zsh -c '> test.txt for x in a b c ; do echo $x; done '
Run Code Online (Sandbox Code Playgroud)

此外,请注意,IFS不会用于拆分像 那样的静态字符串720:500:560:130,分词仅适用于扩展。所以:

$ IFS=":"
$ for a in 720:500:560:130; do echo "$a"; done;
720:500:560:130
Run Code Online (Sandbox Code Playgroud)

但,

$ IFS=":"
$ s=720:500:560:130
$ for a in $s; do echo "$a"; done;
720
500
560
130
Run Code Online (Sandbox Code Playgroud)


归档时间:

查看次数:

190 次

最近记录:

4 年,6 月 前