之前从网上找了很多关于 IFS 的二手资料,每次用每次都得再看一遍,理解还是不够透彻。最近对照着 man bash ,终于把这个 IFS 搞清楚了。

IFS 的三种作用

IFS 其实只在 3 个地方发挥作用:

  1. 用于扩展带双引号的 "$*"
  2. 用于不带双引号的变量扩展 / 子命令扩展 / 算数扩展
  3. 用于在内建命令 read 中进行断词

可以看到,其实只有 bash 本身和 read 命令会用到 IFS 这个环境变量。所以,除了

IFS=xxx bash -c "xxx"

IFS=xxx read a b c

之外,任何的 IFS=xxx 临时环境变量都是不会起到任何作用的。

辅助工具

先写一个小的辅助程序,名为 argsecho,用于直观展示所有参数列表。

import sys
for ind, arg in enumerate(sys.argv[1:], 1):
    print("${}: {}".format(ind, arg), flush=True)

1. 用于扩展带双引号的 $*

对于一个数组

arr=(1 2 3 4 5)

"${arr[@]}" 会展开为 "1" "2" "3" "4" "5" ,是最忠实于原数组的展开方式。通常用于将参数列表原封不动传递给子命令。展开的过程中不涉及 IFS。

$ argsecho "${arr[@]}"
$1: 1
$2: 2
$3: 3
$4: 4
$5: 5

${arr[*]} 则会读取 IFS 的第一个字符,作为分隔符。设为 c,则会展开为 "1c2c3c4c5"。如果 IFS 为空,则直接拼接,不插入分隔符,直接展开为"12345"