在Bash脚本中,我希望将一行分割成多个片段,并将它们存储在一个数组中。
例如,给定一行:
Paris, France, Europe
我想让结果数组看起来像这样:
array[0] = Paris
array[1] = France
array[2] = Europe
最好是一个简单的实现;速度并不重要。我该怎么做呢?
在Bash脚本中,我希望将一行分割成多个片段,并将它们存储在一个数组中。
例如,给定一行:
Paris, France, Europe
我想让结果数组看起来像这样:
array[0] = Paris
array[1] = France
array[2] = Europe
最好是一个简单的实现;速度并不重要。我该怎么做呢?
当前回答
下面是一种不设置IFS的方法:
string="1:2:3:4:5"
set -f # avoid globbing (expansion of *).
array=(${string//:/ })
for i in "${!array[@]}"
do
echo "$i=>${array[i]}"
done
这个想法是使用字符串替换:
${string//substring/replacement}
将所有匹配的$substring替换为空白,然后使用替换后的字符串初始化数组:
(element1 element2 ... elementN)
注意:这个答案使用了split+glob操作符。因此,为了防止某些字符(如*)的扩展,暂停该脚本的通配符是个好主意。
其他回答
IFS=', ' read -r -a array <<< "$string"
请注意,$IFS中的字符被单独视为分隔符,因此在这种情况下,字段可以用逗号或空格分隔,而不是两个字符的序列。但有趣的是,当输入中出现逗号时,不会创建空字段,因为空格是经过特殊处理的。
要访问单个元素:
echo "${array[0]}"
要遍历元素:
for element in "${array[@]}"
do
echo "$element"
done
要同时获取索引和值:
for index in "${!array[@]}"
do
echo "$index ${array[index]}"
done
最后一个示例很有用,因为Bash数组很稀疏。换句话说,您可以删除一个元素或添加一个元素,然后索引不是连续的。
unset "array[1]"
array[42]=Earth
获取数组中元素的个数:
echo "${#array[@]}"
如上所述,数组可以是稀疏的,所以不应该使用长度来获取最后一个元素。以下是在Bash 4.2及以后版本中可以做到的:
echo "${array[-1]}"
在任何版本的Bash中(从2.05b之后的某个地方):
echo "${array[@]: -1:1}"
较大的负偏移量选择距离数组末端更远的位置。注意旧形式中负号前面的空格。这是必须的。
这适用于给定的数据:
$ aaa='Paris, France, Europe'
$ mapfile -td ',' aaaa < <(echo -n "${aaa//, /,}")
$ declare -p aaaa
结果:
declare -a aaaa=([0]="Paris" [1]="France" [2]="Europe")
它也适用于带空格的扩展数据,例如“New York”:
$ aaa="New York, Paris, New Jersey, Hampshire"
$ mapfile -td ',' aaaa < <(echo -n "${aaa//, /,}")
$ declare -p aaaa
结果:
declare -a aaaa=([0]="New York" [1]="Paris" [2]="New Jersey" [3]="Hampshire")
另一种方法是:
string="Paris, France, Europe"
IFS=', ' arr=(${string})
现在你的元素被存储在“arr”数组中。 要遍历元素:
for i in ${arr[@]}; do echo $i; done
#!/bin/bash
string="a | b c"
pattern=' | '
# replaces pattern with newlines
splitted="$(sed "s/$pattern/\n/g" <<< "$string")"
# Reads lines and put them in array
readarray -t array2 <<< "$splitted"
# Prints number of elements
echo ${#array2[@]}
# Prints all elements
for a in "${array2[@]}"; do
echo "> '$a'"
done
此解决方案适用于较大的分隔符(多个字符)。 如果在原始字符串中已经有换行符,则不工作
这适用于我在OSX:
string="1 2 3 4 5"
declare -a array=($string)
如果你的字符串有不同的分隔符,首先用空格替换它们:
string="1,2,3,4,5"
delimiter=","
declare -a array=($(echo $string | tr "$delimiter" " "))
简单:-)