如何用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 ','!
答案 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