我正在尝试将子shell中的输出行读入数组,并且我不愿意设置IFS,因为它是全局的。我不希望脚本的一部分影响以下部分,因为这是不好的做法,我拒绝这样做。在命令不是一个选项后恢复IFS,因为在编辑脚本后将reversion保持在正确的位置太麻烦了。我如何向bash解释我希望每个数组元素都包含整行,而不必设置任何会破坏未来命令的全局变量?
这是一个显示IFS不必要的粘性的例子:
lines=($(egrep "^-o" speccmds.cmd))
echo "${#lines[@]} lines without IFS"
IFS=$'\r\n' lines=($(egrep "^-o" speccmds.cmd))
echo "${#lines[@]} lines with IFS"
lines=($(egrep "^-o" speccmds.cmd))
echo "${#lines[@]} lines without IFS?"
输出结果为:
42 lines without IFS
6 lines with IFS
6 lines without IFS?
答案 0 :(得分:11)
这个问题可能是基于误解。
IFS=foo read
不会在读取操作本身之外更改IFS。
因此,这会产生副作用,应该避免:
IFS=
declare -a array
while read -r; do
array+=( "$REPLY" )
done < <(your-subshell-here)
...但这完全没有副作用:
declare -a array
while IFS= read -r; do
array+=( "$REPLY" )
done < <(your-subshell-here)
使用bash 4.0或更新版本时,还可以选择readarray
或mapfile
(同一操作的同义词):
mapfile -t array < <(your-subshell-here)
在后面添加到答案中的示例中,您的代码如下:
lines=($(egrep "^-o" speccmds.cmd))
更好的方法是:
mapfile -t lines < <(egrep "^-o" speccmds.cmd)
答案 1 :(得分:6)
您是要尝试将输出的行存储在数组中,还是
行
mapfile -t arrayname < <(your subshell)
这根本不使用IFS。
字
(your subshell) | while IFS=: read -ra words; do ...
表单var=value command args...
将var
变量放入command
的环境中,不会影响当前shell的环境。