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

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


当前回答

这也适用于:

IN="bla@some.com;john@home.com"
echo ADD1=`echo $IN | cut -d \; -f 1`
echo ADD2=`echo $IN | cut -d \; -f 2`

小心,这个解决方案并不总是正确的。万一你通过了“bla@some.com“仅,它将分配给ADD1和ADD2。

其他回答

简单答案:

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

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

样本输出:

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

我看到了一些引用cut命令的答案,但它们都被删除了。有点奇怪的是,没有人详细阐述过这一点,因为我认为这是执行这类任务更有用的命令之一,尤其是用于解析分隔的日志文件。

在将这个特定示例拆分为bash脚本数组的情况下,tr可能效率更高,但可以使用cut,如果您想从中间拉取特定字段,则更有效。

例子:

$ echo "bla@some.com;john@home.com" | cut -d ";" -f 1
bla@some.com
$ echo "bla@some.com;john@home.com" | cut -d ";" -f 2
john@home.com

显然,您可以将其放入一个循环中,并迭代-f参数以独立拉动每个字段。

当您有一个分隔的日志文件,其中包含如下行时,这会更有用:

2015-04-27|12345|some action|an attribute|meta data

cut非常方便,能够抓取这个文件并选择一个特定的字段进行进一步处理。

你可以在很多情况下应用awk

echo "bla@some.com;john@home.com"|awk -F';' '{printf "%s\n%s\n", $1, $2}'

你也可以用这个

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

有一种简单而聪明的方法:

echo "add:sfff" | xargs -d: -i  echo {}

但是您必须使用gnu-xargs,BSD-xargs不能支持-d delim。如果你像我一样使用苹果mac,你可以安装gnu-xargs:

brew install findutils

then

echo "add:sfff" | gxargs -d: -i  echo {}

在Bash中,这是一种防弹的方式,即使您的变量包含换行符,也可以使用:

IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in")

看:

$ in=$'one;two three;*;there is\na newline\nin this field'
$ IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in")
$ declare -p array
declare -a array='([0]="one" [1]="two three" [2]="*" [3]="there is
a newline
in this field")'

这项工作的诀窍是使用带有空分隔符的-d选项read(delimiter),这样read就被迫读取它所输入的所有内容。而且,由于printf,我们将read与中变量的内容完全匹配,没有换行符。注意,我们还在printf中放置分隔符,以确保传递给读取的字符串具有尾随分隔符。如果没有它,read将删除可能的尾随空字段:

$ in='one;two;three;'    # there's an empty field
$ IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in")
$ declare -p array
declare -a array='([0]="one" [1]="two" [2]="three" [3]="")'

保留后面的空字段。


Bash≥4.4的更新

从Bash 4.4开始,内置映射文件(也称为readarray)支持-d选项来指定分隔符。因此,另一种规范方法是:

mapfile -d ';' -t array < <(printf '%s;' "$in")