我有一个变量:
var='/path/to/filename.ext
/path/to/filename2.ext
/path/to/filename3.ext'
我想把所有字符串换成换行符的新行:
declare -a arr
基于StackOverflow上的众多帖子,我找到了几种方法:
# method 1: while loop
while read line; do
arr+=($line)
done <<< "$var"
# method 2: readarray
readarray -t arr <<< "$var"
# method 3:
IFS=$'\n'
arr=("$var")
然而,在我学习所有这些方法之前,我正在使用另一种方法,即:
# method 4 (not working in the current situation)
IFS=$'\n'
read -a arr <<< "$var"
这不起作用,因为它只会在var
中存储arr[0]
的第一个字符串。我不明白为什么它在分隔符是换行符的情况下不起作用,而 与其他分隔符一起工作,例如:
IFS='|'
strings='/path/to/filename.ext|/path/to/filename2.ext|'
read -a arr <<< "$strings"
我有什么遗失的东西吗?
删除了我自己的答案,认为你不能将read
用于此目的。事实证明你可以。
答案 0 :(得分:7)
事实证明你的答案错误。是的你可以!您需要使用-d
切换到read
:
-d
delimdelim 的第一个字符用于终止输入行,而不是换行符。
如果将它与空参数一起使用,bash使用空字节作为分隔符:
$ var=$'/path/to/filename.ext\n/path/to/filename2.ext\n/path/to/filename3.ext'
$ IFS=$'\n' read -r -d '' -a arr < <(printf '%s\0' "$var")
$ declare -p arr
declare -a arr='([0]="/path/to/filename.ext" [1]="/path/to/filename2.ext" [2]="/path/to/filename3.ext")'
成功。在这里,我们使用printf
的进程替换,只使用尾随的空字节转储变量的内容,以便read
满意并返回成功返回代码。你可以使用:
IFS=$'\n' read -r -d '' -a arr <<< "$var"
在这种情况下,arr
的内容是相同的;唯一的区别是read
的返回码是1
(失败)。
作为旁注:
之间存在差异$ IFS=$'\n'
$ read ...
和
$ IFS=$'\n' read ...
前者设置全局IFS
(即IFS
将为脚本的其余部分保留此值 - 当然,直到您再次修改它:你很可能不会'我想这样做!
后者仅为命令IFS
设置read
。 你当然希望以这种方式使用它!
另一个注意事项:关于你的方法1.你缺少引号,你没有取消设置IFS
,而你没有使用-r
标志来read
。这很糟糕:
while read line; do
arr+=($line)
done <<< "$var"
这很好:
while IFS= read -r line; do
arr+=( "$line" )
done <<< "$var"
为什么?
IFS
,您将获得前导空格和尾随空格。-r
,一些反斜杠将被理解为转义反斜杠(\'
,尾随\
,\
,以及其他人。)( "$line" )
,您将获得分词和文件名扩展功能:如果您的输入包含空格或全局字符(例如*
,{{1} },[
等。)。