我将此字符串存储在变量中:
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
重置为默认值?
RE: 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
括弧,它可以工作。
#1楼
单线分割用';'分隔的字符串 放入数组是:
IN="bla@some.com;john@home.com"
ADDRS=( $(IFS=";" echo "$IN") )
echo ${ADDRS[0]}
echo ${ADDRS[1]}
这仅将IFS设置在子外壳中,因此您不必担心保存和恢复其值。
#2楼
这也适用:
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。
#3楼
这里有一些很酷的答案(特别是错误),但是对于类似于其他语言的拆分来说,这就是我最初想表达的意思,我就此解决了:
IN="bla@some.com;john@home.com"
declare -a a="(${IN/;/ })";
现在, ${a[0]}
, ${a[1]}
等与您期望的一样。 使用${#a[*]}
表示字词数量。 还是要迭代,当然:
for i in ${a[*]}; do echo $i; done
重要的提示:
这在没有空间可担心的情况下可以解决我的问题,但可能无法解决您的问题。 在这种情况下,请使用$IFS
解决方案。
#4楼
我认为AWK是解决您问题的最佳且有效的命令。 默认情况下,几乎每个Linux发行版都包含AWK。
echo "bla@some.com;john@home.com" | awk -F';' '{print $1,$2}'
会给
bla@some.com john@home.com
当然,您可以通过重新定义awk打印字段来存储每个电子邮件地址。
#5楼
兼容答案
对于这个SO问题,在bash中已经有很多不同的方法可以做到这一点。 但是bash具有许多特殊功能,即所谓的bashism可以很好地工作,但是不能在任何其他shell中工作 。
特别是, 数组 , 关联数组和模式替换是纯bashism ,在其他shell下可能不起作用。
在我的Debian GNU / Linux上 ,有一个称为dash的标准外壳,但是我知道很多人喜欢使用ksh 。
最后,在很小的情况下,有一个名为busybox的特殊工具,带有他自己的外壳解释器( ash )。
要求的字串
SO问题中的字符串示例是:
IN="bla@some.com;john@home.com"
由于这可能对空格有用,并且因为空格可以修改例程的结果,所以我更喜欢使用以下示例字符串:
IN="bla@some.com;john@home.com;Full Name <fulnam@other.org>"
根据bash中的定界符分割字符串(版本> = 4.2)
在纯 bash下,我们可以使用数组和IFS :
var="bla@some.com;john@home.com;Full Name <fulnam@other.org>"
oIFS="$IFS" IFS=";" declare -a fields=($var) IFS="$oIFS" unset oIFS
IFS=\; read -a fields <<<"$IN"
在最近的bash下使用此语法不会为当前会话更改$IFS
,而仅会为当前命令更改:
set | grep ^IFS=
IFS=$' \t\n'
现在&