在Bash中将定界字符串读入数组


206

我有一个包含以空格分隔的字符串的变量:

line="1 1.50 string"

我想用空格作为分隔符来拆分该字符串,并将结果存储在数组中,以便执行以下操作:

echo ${arr[0]}
echo ${arr[1]}
echo ${arr[2]}

输出

1
1.50
string

我在某个地方找到了行不通的解决方案:

arr=$(echo ${line})

如果在此之后运行上面的echo语句,则会得到:

1 1.50 string
[empty line]
[empty line]

我也试过

IFS=" "
arr=$(echo ${line})

具有相同的结果。有人可以帮忙吗?


在Unix&Linux Stack Exchange上查看以下答案:将sed与herestring(<<<)和read -a一起使用set -f; arr=($string); set +f似乎比快read -r -a <<< $string
codeforester

Answers:


331

为了将字符串转换为数组,请使用

arr=($line)

要么

read -a arr <<< $line

至关重要的是不要使用引号,因为这样做可以解决问题。


7
并对您的新阵列进行完整性检查:for i in ${arr[@]}; do echo $i; done
Banjer 2013年

5
或者只是echo ${arr[@]}
Banjer

13
如果其中$line包含通配符,则两种方法都可能失败。mkdir x && cd x && touch A B C && line="*" arr=($line); echo ${#arr[@]}给出3
Tino 2014年

3
declare -a "arr=($line)"会忽略带IFS引号的字符串中的分隔符
Dave

4
@Tino否。当时line='*'read -a arr <<<$line始终有效,但只会arr=($line)失败。
Johnny Wong

39

试试这个:

arr=(`echo ${line}`);

5
尼斯-此解决方案也可以在Z shell中使用,而上述其他方法也会失败。
Keith Hughitt 2014年

它的工作原理,请您解释一下它为什么有效吗?
smartwjw

2
备注:当行中带有'*'时,这也不起作用,例如line='*'
Johnny Wong

34

在:中arr=( $line )。“拆分”与“全局”关联。
通配符(*?[])将扩大到匹配文件名。

正确的解决方案只是稍微复杂一点:

IFS=' ' read -a arr <<< "$line"

没有球状问题;拆分字符设置在$IFS,引用的变量中。


5
这应该是公认的答案。公认答案中的陈述arr=($line)存在问题。例如,尝试:。line="twinkling *"; arr=($line); declare -p arr
Codeforester

对于herestring,引用是可选的,<<<但是为了保持一致性和可读性,仍然使用双引号可能是一个好主意。
codeforester

6

如果需要参数扩展,请尝试:

eval "arr=($line)"

例如,采用以下代码。

line='a b "c d" "*" *'
eval "arr=($line)"
for s in "${arr[@]}"; do 
    echo "$s"
done

如果当前目录包含的文件a.txtb.txt并且c.txt,然后执行该代码会产生以下输出。

a
b
c d
*
a.txt
b.txt
c.txt

-9
line="1 1.50 string"

arr=$( $line | tr " " "\n")

for x in $arr
do
echo "> [$x]"
done

循环是错误的,它将数组拆分得很细,管道变成了tr多余的,但是应该循环,"${arr[@]}"而不是$arr
Zorf
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.