我将此字符串存储在变量中:

IN="bla@some.com;john@home.com"

现在,我想将字符串拆分为:;分隔符,以便我可以:

ADDR1="bla@some.com"
ADDR2="john@home.com"

我不一定需要ADDR1和ADDR2变量。如果它们是数组的元素,那就更好了。


根据以下答案的建议,我最终得出了以下结论,这就是我想要的:

#!/usr/bin/env bash

IN="bla@some.com;john@home.com"

mails=$(echo $IN | tr ";" "\n")

for addr in $mails
do
    echo "> [$addr]"
done

输出:

> [bla@some.com]
> [john@home.com]

有一个解决方案涉及将Internal_field_separator(IFS)设置为;。我不确定这个答案发生了什么,如何将IFS重置为默认值?

回复:IFS解决方案,我尝试了这个,它奏效了,我保留了旧的IFS,然后恢复它:

IN="bla@some.com;john@home.com"

OIFS=$IFS
IFS=';'
mails2=$IN
for x in $mails2
do
    echo "> [$x]"
done

IFS=$OIFS

顺便说一下,当我尝试

mails2=($IN)

在循环中打印时,我只得到了第一个字符串,$in周围没有括号,它可以工作。


当前回答

以下Bash/zsh函数将其第一个参数拆分为第二个参数给出的分隔符:

split() {
    local string="$1"
    local delimiter="$2"
    if [ -n "$string" ]; then
        local part
        while read -d "$delimiter" part; do
            echo $part
        done <<< "$string"
        echo $part
    fi
}

例如,命令

$ split 'a;b;c' ';'

产量

a
b
c

例如,该输出可以通过管道传输到其他命令。例子:

$ split 'a;b;c' ';' | cat -n
1   a
2   b
3   c

与给出的其他解决方案相比,该解决方案具有以下优点:

IFS没有被覆盖:由于甚至局部变量的动态作用域,在循环上覆盖IFS会导致新值泄漏到从循环内执行的函数调用中。不使用数组:使用read将字符串读入数组需要Bash中的-a标志和zsh中的-a标志。

如果需要,可以将函数放入脚本,如下所示:

#!/usr/bin/env bash

split() {
    # ...
}

split "$@"

其他回答

也许不是最优雅的解决方案,但可以使用*和空格:

IN="bla@so me.com;*;john@home.com"
for i in `delims=${IN//[^;]}; seq 1 $((${#delims} + 1))`
do
   echo "> [`echo $IN | cut -d';' -f$i`]"
done

输出

> [bla@so me.com]
> [*]
> [john@home.com]

其他示例(开头和结尾的分隔符):

IN=";bla@so me.com;*;john@home.com;"
> []
> [bla@so me.com]
> [*]
> [john@home.com]
> []

基本上,它会删除除以下字符以外的所有字符:;制作熟食;;;。然后,它执行从1到${#delims}计数的分隔符数的循环。最后一步是使用切割安全地获得$i部分。

IN="bla@some.com;john@home.com"
IFS=';'
read -a IN_arr <<< "${IN}"
for entry in "${IN_arr[@]}"
do
    echo $entry
done

输出

bla@some.com
john@home.com

系统:Ubuntu 12.04.1

这对我有用:

string="1;2"
echo $string | cut -d';' -f1 # output is 1
echo $string | cut -d';' -f2 # output is 2
echo "bla@some.com;john@home.com" | sed -e 's/;/\n/g'
bla@some.com
john@home.com

这是一个干净的3行:

in="foo@bar;bizz@buzz;fizz@buzz;buzz@woof"
IFS=';' list=($in)
for item in "${list[@]}"; do echo $item; done

其中IFS根据分隔符分隔单词,()用于创建数组。然后使用[@]将每个项目作为单独的单词返回。

如果之后有任何代码,还需要恢复$IFS,例如未设置IFS。