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

例如,给定一行:

Paris, France, Europe

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

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

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


当前回答

更新:不要这样做,由于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操作符。因此,为了防止某些字符(如*)的扩展,暂停该脚本的通配符是个好主意。

当我想解析一个输入时,我看到了这篇文章: word1 word2,…

以上这些对我都没有帮助。使用awk解决了这个问题。如果它能帮助某人:

STRING="value1,value2,value3"
array=`echo $STRING | awk -F ',' '{ s = $1; for (i = 2; i <= NF; i++) s = s "\n"$i; print s; }'`
for word in ${array}
do
        echo "This is the word $word"
done

接受的答案适用于一行中的值。如果变量有几行:

string='first line
        second line
        third line'

我们需要一个非常不同的命令来获取所有的行:

While read -r line;做线+ =(“美元线”);完成了< < <字符串" $ "

或者更简单的bash readarray:

readarray -t lines <<<"$string"

利用printf特性很容易打印所有行:

printf ">[%s]\n" "${lines[@]}"

>[first line]
>[        second line]
>[        third line]

这适用于给定的数据:

$ 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")

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

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

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

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

这是基于Dennis Williamson的回答。