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

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周围没有括号,它可以工作。


当前回答

又一个迟来的答案。。。如果你对java有兴趣,这里是bashj(https://sourceforge.net/projects/bashj/)解决方案:

#!/usr/bin/bashj

#!java

private static String[] cuts;
private static int cnt=0;
public static void split(String words,String regexp) {cuts=words.split(regexp);}
public static String next() {return(cnt<cuts.length ? cuts[cnt++] : "null");}

#!bash

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

: j.split($IN,";")    # java method call

while true
do
    NAME=j.next()     # java method call
    if [ $NAME != null ] ; then echo $NAME ; else exit ; fi
done

其他回答

这是最简单的方法。

spo='one;two;three'
OIFS=$IFS
IFS=';'
spo_array=($spo)
IFS=$OIFS
echo ${spo_array[*]}

简单答案:

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

IFS=';' read ADDR1 ADDR2 <<< "${IN}"

样本输出:

echo "${ADDR1}"  # prints "bla@some.com"
echo "${ADDR2}"  # prints "john@home.com"

您可以设置内部字段分隔符(IFS)变量,然后让它解析为数组。当在命令中发生这种情况时,IFS的赋值只发生在单个命令的环境中(读取)。然后,它根据IFS变量值将输入解析为数组,然后我们可以对其进行迭代。

此示例将解析一行由;,将其推入阵列:

IFS=';' read -ra ADDR <<< "$IN"
for i in "${ADDR[@]}"; do
  # process "$i"
done

另一个示例用于处理$IN的整个内容,每次一行输入由;:

while IFS=';' read -ra ADDR; do
  for i in "${ADDR[@]}"; do
    # process "$i"
  done
done <<< "$IN"

我认为AWK是解决您问题的最佳有效命令。AWK默认包含在几乎每个Linux发行版中。

echo "bla@some.com;john@home.com" | awk -F';' '{print $1,$2}'

将给予

bla@some.com john@home.com

当然,您可以通过重新定义awk打印字段来存储每个电子邮件地址。

IN='bla@some.com;john@home.com;Charlie Brown <cbrown@acme.com;!"#$%&/()[]{}*? are no problem;simple is beautiful :-)'
set -f
oldifs="$IFS"
IFS=';'; arrayIN=($IN)
IFS="$oldifs"
for i in "${arrayIN[@]}"; do
echo "$i"
done
set +f

输出:

bla@some.com
john@home.com
Charlie Brown <cbrown@acme.com
!"#$%&/()[]{}*? are no problem
simple is beautiful :-)

说明:使用括号()的简单赋值将分号分隔的列表转换为数组,前提是在执行此操作时使用正确的IFS。标准FOR循环照常处理该数组中的各个项。请注意,为IN变量提供的列表必须是“硬”引号,即带有单引号。

必须保存和恢复IFS,因为Bash不会像对待命令一样对待赋值。另一种解决方法是将赋值包装在函数内,并使用修改后的IFS调用该函数。在这种情况下,不需要单独保存/恢复IFS。感谢“比兹”指出这一点。