我将此字符串存储在变量中:
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;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。感谢“比兹”指出这一点。
两种都不需要bash数组的伯尔尼式替代方案:
案例1:保持简洁:使用NewLine作为记录分隔符。。。如。
IN="bla@some.com
john@home.com"
while read i; do
# process "$i" ... eg.
echo "[email:$i]"
done <<< "$IN"
注意:在第一种情况下,没有分支子进程来帮助列表操作。
想法:也许值得在内部广泛使用NL,在外部生成最终结果时只转换为不同的RS。
案例2:使用“;”作为记录分隔符。。。如。
NL="
" IRS=";" ORS=";"
conv_IRS() {
exec tr "$1" "$NL"
}
conv_ORS() {
exec tr "$NL" "$1"
}
IN="bla@some.com;john@home.com"
IN="$(conv_IRS ";" <<< "$IN")"
while read i; do
# process "$i" ... eg.
echo -n "[email:$i]$ORS"
done <<< "$IN"
在这两种情况下,子列表都可以在循环中组成。循环完成后,子列表是持久的。这在处理内存中的列表时非常有用,而不是将列表存储在文件中。{请保持冷静,继续进行B-)}