拆分字符串(例如使用bash)但跳过部分字符串

时间:2014-08-17 12:51:30

标签: linux bash awk sed

如何用bash(awk,sed等)分割以下字符串:

在:

a,b,[c, d],e

输出:

a
b
[c, d]
e

尝试1)

$IFS=',' read -a tokens <<< "a,b,[c, d], e"; echo ${tokens[@]}
a b [c d] e

尝试2)

$ IFS=',' 
$ line="a,b,[c, d], e"
$ eval x=($line)
$ echo ${x[1]}
b
$ echo ${x[0]}
a
$ echo ${x[2]}
[c  d]

But not ','!

4 个答案:

答案 0 :(得分:4)

这只是一般CSV问题的一个特定实例,用于识别引号内的逗号与引号之外的逗号不同,以便用其他字符替换任何一个(例如;)。对此的惯用awk解决方案(除了在GNU awk中使用FPAT)是:

在引号内替换:

$ echo 'a,b,"c, d",e' | awk 'BEGIN{FS=OFS="\""} {for (i=2;i<=NF;i+=2) gsub(/,/,";",$i)}1'
a,b,"c; d",e

在引号外替换:

$ echo 'a,b,"c, d",e' | awk 'BEGIN{FS=OFS="\""} {for (i=1;i<=NF;i+=2) gsub(/,/,";",$i)}1'
a;b;"c, d";e

在您的情况下,分隔符为[...]而不是"...",替换字符是换行符而不是分号,但它基本上是同一个问题:

替换&#34;报价&#34; (方括号):

$ echo 'a,b,[c, d],e' | awk 'BEGIN{FS="[][]"; OFS=""} {for (i=1;i<=NF;i+=2) gsub(/,/,"\n",$i)}1'
a
b
c, d
e

请注意,方括号不见了,因为我将OFS设置为空白字符,因为没有1个单独的FS字符可供使用。如果你确实需要它们,你可以用它来取回它们:

$ echo 'a,b,[c, d],e' | awk 'BEGIN{FS="[][]"; OFS=""} {for (i=1;i<=NF;i++) if (i%2) gsub(/,/,"\n",$i); else $i="["$i"]"}1'
a
b
[c, d]
e

但是你没有机会,因为他们的目的是对包含逗号的文本进行分组,现在由新行处理的是字段分隔符而不是逗号。

答案 1 :(得分:2)

例如,你可以使用这个grep:

grep -Po '([a-z]|\[[a-z], [a-z]\])'
           ^^^^^ ^^^^^^^^^^^^^^^^ 

请参阅:

$ echo "a,b,[c, d],e" | grep -Po '([a-z]|\[[a-z], [a-z]\])'
a
b
[c, d]
e

也就是说,使用grep仅打印(因此-o仅匹配),[a-z]个字母或[ + [a-z], [a-z]块+ ]

或者您也可以将开场[和结束, [a-z]]块设为可选:

$ echo "a,b,[c, d],e" | grep -Po '(\[)?[a-z](, [a-z]\])?'
a
b
[c, d]
e

答案 2 :(得分:1)

匹配以[开头且以]结尾的所有内容:\[[^][]*\]。 然后匹配任何不是逗号的内容:[^,]\+

echo 'a,b,[c, d],e' | grep -o -e '\[[^][]*\]' -e '[^,]\+'

输出:

a
b
[c, d]
e

答案 3 :(得分:1)

echo "a,b,[c, d],e" | grep -o '\[.*\]\|[^,]*'

输出:

a
b
[c, d]
e