sed和regex替换','除了字符串内部

时间:2014-02-08 16:12:19

标签: regex sed

我输入了以下架构

10,0,'string1_string2,_string3','',8,0,0,0.59,'20140101205216','20140128074836',584266915,5934

我想用sed替换所有逗号“,”字符和标签。约束是不替换文本字符串中的“,”(即'string1_string2,_string3'中的逗号不应替换为tab)。执行此操作的正则表达式是(?!,_)。

但是以下sed不起作用。我也试过了所有逃避的排列。

sed s/",\(\?\!,_\)"/"\t"/g 

有办法做到这一点吗?

4 个答案:

答案 0 :(得分:3)

在Mac OS X 10.9.1上,您可以使用:

sed -E -e "s/('[^']*'|[^,]*),/\1X/g"

除了您用实际标签替换X.对于您的输入行,产生:

10X0X'string1_string2,_string3'X''X8X0X0X0.59X'20140101205216'X'20140128074836'X584266915X5934

其中X是你想要标签的地方。使用GNU sed,您可以使用-r代替-E(尽管它也会识别-E)。 Mac sed不会将\t展开到标签页; GNU sed会。使用Bash,您可以使用ANSI-C Quoting机制让shell在传递给sed的字符串中嵌入一个选项卡:

sed -E -e "s/('[^']*'|[^,]*),/\1"$'\t'"/g"

如果没有扩展正则表达式(由-r-E激活),则不值得在sed中尝试;请改用awk

正则表达式查找 单引号后跟零或多个非引号和单引号零或更多非逗号,后跟逗号,并将其替换为记忆为/或字符串和“标签”的内容(使用X表示标签,因为它更加明显)。


devnull points out上面的答案替换了一行末尾的字符串中的逗号。有一个解决方法:

sed -E -e "s/('[^']*'|[^,]*)(,|$)/\1"$'\t'"/g; s/"$'\t'"$//"

分号前的s///g在每行的末尾添加一个制表符;分号后的s///删除刚刚添加的选项卡。

答案 1 :(得分:1)

如果可用的话,我会建议使用Perl的帮助,因为 lookarounds 的可用性:

s="10,0,'string1_string2,_string3','',8,0,0,0.59,'20140101205216','20140128074836',584266915,5934"

perl -pe "s/,(?=(([^']*'){2})*[^']*$)/\t/g" <<< "$s"

10\t0\t'string1_string2,_string3'\t''\t8\t0\t0\t0.59\t'20140101205216'\t'20140128074836'\t584266915\t5934

PS:仅出于可读性目的而显示\t

答案 2 :(得分:1)

您可以使用Text::ParseWords

perl -MText::ParseWords -n -l -e 'print join("\t", parse_line(",", 1, $_));' filename

对于您的输入,结果是:

10      0       'string1_string2,_string3'      ''      8       0       0       0.59    '20140101205216'        '20140128074836'        584266915       5934

答案 3 :(得分:0)

如果我理解你的问题,这似乎有效:

sed -E 's/,([^_])/\t\1/g'

输出:

10  0   'string1_string2,_string3'  ''  8   0   0   0.59    '20140101205216'    '20140128074836'    584266915   5934