使用多个字符作为分隔符将字符串拆分为数组

4

我需要将一个字符串分割成数组。我的问题是分隔符是一个由3个字符组成的: _-_
例如:

db2-111_-_oracle12cR1RAC_-_mariadb101

我需要创建以下数组:

db2-111
oracle12cR1RAC
mariadb101

类似的问题都遵循了这个方法:

str="db2-111_-_oracle12cR1RAC_-_mariadb101"
arr=(${str//_-_/ })
echo ${arr[@]}

即使数组已创建,也可能被错误地分割:
db2 
111 
oracle12cR1RAC 
mariadb101

似乎第一个项目中的"-"字符会导致数组的分割函数失败。 你能提出修复方法吗?谢谢。

5个回答

3
如果可以的话,请用另一个单一字符替换掉_-_序列,以便于你进行字段分割。例如,
$ str="db2-111_-_oracle12cR1RAC_-_mariadb101"
$ str2=${str//_-_/#}
$ IFS="#" read -ra arr <<< "$str2"
$ printf '%s\n' "${arr[@]}"
db2-111
oracle12cR1RAC
mariadb101

2
您可以使用sed来完成您想做的事情,即编写类似于以下内容的内容:
str="db2-111_-_oracle12cR1RAC_-_mariadb101"
arr=($(sed 's/_-_/ /g' <<< $str))
echo ${arr[0]}

编辑:

arr=(${str//_-_/ }) 没有生效的原因是当你像这样写时,${ ... } 内的所有内容都被视为数组的一个元素。因此,使用 sed,甚至只需使用 arr=($(echo ${str//_-_/ })) 即可产生您期望的结果。


谢谢您的建议。不过我已经尝试过了,但是它只生成了一个大小为1的数组: echo ${arr[0]} db2 111 oracle12cR1RAC mariadb101 - Francesco Marchioni
使用转义字符也不起作用 sed "s/\_\-\_/ /g" - Francesco Marchioni
你确定你使用的是我给的完全一样的代码吗?在我的电脑上(使用GNU sed),复制/粘贴我的代码可以在zshbash-4.4bash-3.2上运行。 - Aserre
确实有点奇怪。代码是一样的。我正在运行bash 4.3.43(1)版本。 - Francesco Marchioni
1
@FrancescoMarchioni 如果你在bash 4.3中设置了IFS="_-_",那么你会得到这样的输出,这似乎是你尝试过但忘记重置的东西。此代码假定IFS具有其默认值。 - chepner

1
<<<'db2-111_-_oracle12cR1RAC_-_mariadb101' | 

{m,g}awk NF=NF FS='_[-]_' OFS='\n'

db2-111
oracle12cR1RAC
mariadb101

如果您喜欢流行但特别简练的RS语法,那么这就是适合您的选择。

mawk ~ RS='_-_|\n'

   or

mawk \$_ RS='_-_|\n'

   or simply

mawk RS RS='_-_|\n'

db2-111
oracle12cR1RAC
mariadb101

0
使用 Perl one-liner。
$ echo "db2-111_-_oracle12cR1RAC_-_mariadb101" | perl -F/_-_/ -ne ' { print "$F[0]\n$F[1]\n$F[2]" } '
db2-111
oracle12cR1RAC
mariadb101

0

这里提供了一种解决方案,使用替换_-_为NUL字节,因为我们不能安全地假设输入字符串中不会出现某些字符,例如#;:

readarray -d '' arr < <(
   awk -F'_-_' -v OFS='\0' '{ORS=OFS; $1=$1} 1' <<< "$str")

declare -p arr
declare -a arr=([0]="db2-111" [1]="oracle12cR1RAC" [2]="mariadb101")

请注意,由于使用了readarray命令,所以需要BASH版本4或更高。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接