我输入了以下架构
10,0,'string1_string2,_string3','',8,0,0,0.59,'20140101205216','20140128074836',584266915,5934
我想用sed替换所有逗号“,
”字符和标签。约束是不替换文本字符串中的“,
”(即'string1_string2,_string3'
中的逗号不应替换为tab)。执行此操作的正则表达式是(?!,_)。
但是以下sed不起作用。我也试过了所有逃避的排列。
sed s/",\(\?\!,_\)"/"\t"/g
有办法做到这一点吗?
答案 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