神秘 IFS 行为
Mysteries IFS behavior
这里 我了解到我可以通过设置 IFS 将字符串拆分为数组。
这里 我了解到我可以通过 IFS 定界符连接数组。
但在我下面的测试中:
0:~ $ a=(1 2 3)
0:~ $ echo "${a[*]}"
1 2 3
0:~ $ IFS=. echo "${a[*]}" # IFS=. not work
1 2 3
0:~ $ (IFS=.; echo "${a[*]}") # this works
1.2.3
0:~ $ echo $IFS # the original IFS is not change
0:~ $ v=1.2.3
0:~ $ IFS=. b=($v) # change string to array
0:~ $ echo ${b[*]}
1 2 3
0:~ $ echo "${b[*]}" # the array join by `.`!
1.2.3
0:~ $ echo ${b}
1
0:~ $ (IFS=,; echo "${b[*]}") # this still work
1,2,3
0:~ $ IFS=, echo "${b[*]}" # this not work, b array still join by .
1.2.3
0:~ $ c=(1 2 3)
0:~ $ echo "${c[*]}" # a new array join by '.' !
1.2.3
0:~ $ IFS=, echo "${c[*]}" # IFS=, not work, still join by '.'
1.2.3
0:~ $ (IFS=,; echo "${c[*]}") # this works
1,2,3
0:~ $ echo $IFS # original IFS is space
0:~ $ bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)
Copyright (C) 2007 Free Software Foundation, Inc.
从上面,我有以下guessing/questions:
IFS=. echo "${a[*]}"
这改变了回声环境,但没有改变引用扩展环境,所以它不起作用?
- 如果 1 为真,为什么
IFS=. b=($v)
成功创建数组?
- 为什么
echo "${c[*]}"
加入了 .? IFS 应该是默认的空格。
当您执行 IFS=. b=($v)
两个 shell 赋值时,问题出在 IFS
设置 current shell。将 IFS
修改为 .
将使所有后续的 "${arr[*]}"
类型的数组扩展都使用这个新值。注意这里的双引号,没有引号的相同数组扩展不会使用 IFS
即 ${arr[*]}
所以回答你的问题
IFS=. echo "${a[*]}"
this change the echo environment, but not change the quoting expanding environment, so it's not work?
你错了,尽管你将 IFS
传递给 echo
接收的环境。但是,echo
不对其环境列表执行任何操作。出现此结果是因为您之前将 IFS
的值设置为 .
if 1 is true, why IFS=. b=($v)
successful create the array?
此命令 运行 就像您分别执行这两个命令一样。将IFS
修改为.
,将不带引号的字符串v
的结果展开到分词数组中,值为IFS
。由于您之前已将其定义为 .
,因此该字符串被拆分为单独的组件并存储到数组中。
why echo "${c[*]}"
joined by .? the IFS should be default whitespace.
第一个回答里已经说明了。您已将当前的 shell 修改为使用 IFS
为 .
,随后的数组扩展将采用这些来连接字符串。如果您开始新的 shell 和 运行 相同的扩展,它将无法工作。
再澄清一点,即何时将变量传递到命令的本地环境将起作用。如果不是
var=val echo "$var"
如果你写过
var=val sh -c 'echo "$var"'
你看到写的var
的值,因为在这种情况下,你在环境中传递var
的值,sh
shell是运行。但与echo
不同的是,sh
从环境中读取并看到var
的值,并用它来进行变量扩展。
这里 我了解到我可以通过设置 IFS 将字符串拆分为数组。
这里 我了解到我可以通过 IFS 定界符连接数组。
但在我下面的测试中:
0:~ $ a=(1 2 3)
0:~ $ echo "${a[*]}"
1 2 3
0:~ $ IFS=. echo "${a[*]}" # IFS=. not work
1 2 3
0:~ $ (IFS=.; echo "${a[*]}") # this works
1.2.3
0:~ $ echo $IFS # the original IFS is not change
0:~ $ v=1.2.3
0:~ $ IFS=. b=($v) # change string to array
0:~ $ echo ${b[*]}
1 2 3
0:~ $ echo "${b[*]}" # the array join by `.`!
1.2.3
0:~ $ echo ${b}
1
0:~ $ (IFS=,; echo "${b[*]}") # this still work
1,2,3
0:~ $ IFS=, echo "${b[*]}" # this not work, b array still join by .
1.2.3
0:~ $ c=(1 2 3)
0:~ $ echo "${c[*]}" # a new array join by '.' !
1.2.3
0:~ $ IFS=, echo "${c[*]}" # IFS=, not work, still join by '.'
1.2.3
0:~ $ (IFS=,; echo "${c[*]}") # this works
1,2,3
0:~ $ echo $IFS # original IFS is space
0:~ $ bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)
Copyright (C) 2007 Free Software Foundation, Inc.
从上面,我有以下guessing/questions:
IFS=. echo "${a[*]}"
这改变了回声环境,但没有改变引用扩展环境,所以它不起作用?- 如果 1 为真,为什么
IFS=. b=($v)
成功创建数组? - 为什么
echo "${c[*]}"
加入了 .? IFS 应该是默认的空格。
当您执行 IFS=. b=($v)
两个 shell 赋值时,问题出在 IFS
设置 current shell。将 IFS
修改为 .
将使所有后续的 "${arr[*]}"
类型的数组扩展都使用这个新值。注意这里的双引号,没有引号的相同数组扩展不会使用 IFS
即 ${arr[*]}
所以回答你的问题
IFS=. echo "${a[*]}"
this change the echo environment, but not change the quoting expanding environment, so it's not work?
你错了,尽管你将 IFS
传递给 echo
接收的环境。但是,echo
不对其环境列表执行任何操作。出现此结果是因为您之前将 IFS
的值设置为 .
if 1 is true, why
IFS=. b=($v)
successful create the array?
此命令 运行 就像您分别执行这两个命令一样。将IFS
修改为.
,将不带引号的字符串v
的结果展开到分词数组中,值为IFS
。由于您之前已将其定义为 .
,因此该字符串被拆分为单独的组件并存储到数组中。
why
echo "${c[*]}"
joined by .? the IFS should be default whitespace.
第一个回答里已经说明了。您已将当前的 shell 修改为使用 IFS
为 .
,随后的数组扩展将采用这些来连接字符串。如果您开始新的 shell 和 运行 相同的扩展,它将无法工作。
再澄清一点,即何时将变量传递到命令的本地环境将起作用。如果不是
var=val echo "$var"
如果你写过
var=val sh -c 'echo "$var"'
你看到写的var
的值,因为在这种情况下,你在环境中传递var
的值,sh
shell是运行。但与echo
不同的是,sh
从环境中读取并看到var
的值,并用它来进行变量扩展。