我有一个包含空格分隔字符串的变量:
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})
结果相同。有人可以帮忙吗?
set -f; arr=($string); set +f
似乎比 read -r -a <<< $string
快。
为了将字符串转换为数组,从字符串创建一个数组,让字符串根据 IFS
(内部字段分隔符)变量自然拆分,默认为空格字符:
arr=($line)
或使用 herestring (<<<
) 运算符将字符串传递到 read
命令的标准输入:
read -a arr <<< "$line"
对于第一个示例,not 在 $line
周围使用引号至关重要,因为这样可以将字符串拆分为多个元素。
另请参阅:https://github.com/koalaman/shellcheck/wiki/SC2206
在:arr=( $line )
。 “split”与“glob”相关联。
通配符(*
、?
和 []
)将扩展为匹配的文件名。
正确的解决方案只是稍微复杂一点:
IFS=' ' read -a arr <<< "$line"
没有通配问题;拆分字符设置在 $IFS
中,变量引用。
arr=($line)
存在通配问题。例如,尝试:line="twinkling *"; arr=($line); declare -p arr
。
<<<
,引号是可选的,但为了一致性和可读性,仍然使用双引号可能是个好主意。
尝试这个:
arr=(`echo ${line}`);
line='*'
GNU Make 4.2.1
解决方案,但它没有完成工作
sh
外壳。该外壳没有数组。问题是关于数组的。不能给你一个同时满足这两个要求的答案。除非您声称位置参数是 sh
中唯一的数组,否则, this: set -- $line; printf '%s\n' "$@"
将起作用。请注意,在这种情况下,全局字符仍然是一个问题。
如果您需要参数扩展,请尝试:
eval "arr=($line)"
例如,采用以下代码。
line='a b "c d" "*" *'
eval "arr=($line)"
for s in "${arr[@]}"; do
echo "$s"
done
如果当前目录包含文件 a.txt
、b.txt
和 c.txt
,则执行代码将产生以下输出。
a
b
c d
*
a.txt
b.txt
c.txt
GNU Make 4.2.1
解决方案,但不是这样
line="1 1.50 string"
arr=$( $line | tr " " "\n")
for x in $arr
do
echo "> [$x]"
done
tr
是多余的,但它应该循环 "${arr[@]}"
而不是 $arr
for i in ${arr[@]}; do echo $i; done
echo ${arr[@]}
$line
中有通配符,这两种方法都可能失败。mkdir x && cd x && touch A B C && line="*" arr=($line); echo ${#arr[@]}
给出 3declare -a "arr=($line)"
将忽略带引号的字符串中的IFS
个分隔符line='*'
时,read -a arr <<<$line
始终有效,但只有arr=($line)
失败。