修改IFS后未按预期分割字符串,交互式Shell下如何解决?
在zsh中按
:分割字符串的问题及解决方法 问题场景
在macOS的zsh交互式Shell中执行以下命令:
$ IFS=":" $ for i in "foo:bar:apple"; do echo $i; done foo:bar:apple
修改IFS后预期按:分割字符串,但并未生效;尝试export IFS=":"后结果依旧:
❯ export IFS=":" ❯ for i in "foo:bar:apple"; do echo $i; done foo:bar:apple
问题原因
核心问题是双引号的作用:zsh会将被双引号包裹的字符串视为一个完整的整体,不会触发基于IFS的分词操作,所以无论怎么修改IFS,都不会分割这个带引号的字符串。
解决方法
下面是几种在交互式zsh中实现按:分割字符串的可行方式:
方法1:移除引号触发IFS分词
直接去掉字符串的双引号,让zsh基于设置的IFS进行分词:
IFS=":" for i in foo:bar:apple; do echo $i; done
执行后输出:
foo bar apple
方法2:使用zsh参数展开(无需修改IFS)
如果字符串存储在变量中,可以用zsh专属的参数展开语法,不用修改全局IFS:
str="foo:bar:apple" for i in ${(s.:.)str}; do echo $i; done
其中(s.:.)是zsh的参数展开标记,指定用:作为分隔符分割变量str。
方法3:用read命令存入数组
通过read命令配合IFS将字符串分割后存入数组,再遍历数组:
IFS=":" read -r -a parts <<< "foo:bar:apple" for i in "${parts[@]}"; do echo $i; done
read -a参数会把分割后的每一项存入数组parts,后续直接遍历数组即可。
注意事项
如果不想让修改后的IFS影响后续命令,建议临时修改:
- 用子shell隔离环境:
(IFS=":"; for i in foo:bar:apple; do echo $i; done)
- 先保存原IFS,用完恢复:
OLD_IFS=$IFS IFS=":" for i in foo:bar:apple; do echo $i; done IFS=$OLD_IFS
内容的提问来源于stack exchange,提问作者monte
相关产品推荐
相关产品推荐

