在Bash脚本中,我希望将一行分割成多个片段,并将它们存储在一个数组中。

例如,给定一行:

Paris, France, Europe

我想让结果数组看起来像这样:

array[0] = Paris
array[1] = France
array[2] = Europe

最好是一个简单的实现;速度并不重要。我该怎么做呢?


当前回答

另一种不修改IFS的方法是:

read -r -a myarray <<< "${string//, /$IFS}"

我们不需要更改IFS以匹配所需的分隔符,而是可以通过"${string//, /$IFS}"将所有出现的所需分隔符","替换为$IFS的内容。

也许这对于非常大的字符串来说会很慢?

这是基于Dennis Williamson的回答。

其他回答

#!/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

此解决方案适用于较大的分隔符(多个字符)。 如果在原始字符串中已经有换行符,则不工作

更新:不要这样做,由于eval的问题。

不那么讲究礼节的:

IFS=', ' eval 'array=($string)'

e.g.

string="foo, bar,baz"
IFS=', ' eval 'array=($string)'
echo ${array[1]} # -> bar

下面是一种不设置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操作符。因此,为了防止某些字符(如*)的扩展,暂停该脚本的通配符是个好主意。

对于多行元素,为什么不像

$ array=($(echo -e $'a a\nb b' | tr ' ' '§')) && array=("${array[@]//§/ }") && echo "${array[@]/%/ INTERELEMENT}"

a a INTERELEMENT b b INTERELEMENT

这类似于Jmoney38的方法,但是使用sed:

string="1,2,3,4"
array=(`echo $string | sed 's/,/\n/g'`)
echo ${array[0]}

打印1