假设我们在CSV中有一行看起来像这样:
|Foo|,,,,,,,,|Bar|,,,,,
其中|
是封装器,,
是分隔符(如您所料)。
但是说你有一些代码需要填写这些空字段,而你想要将这一行转换成这样的代码:
|Foo|,||,||,||,||,||,||,||,|Bar|,||,||,||,||,
(我们可以稍后处理尾随的逗号) 我试图在此CSV上使用此sed命令来获得所需的结果:
sed 's/,,/,||,/g'
然而,正则表达式,,
不是零宽度,因此当它扫描线时,它会移动两个,即使我们只处理了一个字段。结果是这样的:
|Foo|,||,,||,,||,,||,|Bar|,||,,||,,
问题在于,当我们在替换中取得这样的成果时:
|Foo|,||,,,,,,,|Bar|,,,,,
我们已经'处理'了||
周围的逗号,我们在我们正在使用的最后一个逗号之后移动到下一对,这不涉及最后一个逗号,||,
。
如何使用sed进行此替换?
答案 0 :(得分:1)
快速解决方案是重复替换:
sed 's/,,/,||,/g;s/,,/,||,/g'
答案 1 :(得分:1)
更优雅的方法是使用条件分支:
$ sed ':a;s/,,/,||,/;ta' <<< '|Foo|,,,,,,,,|Bar|,,,,,'
|Foo|,||,||,||,||,||,||,||,|Bar|,||,||,||,||,
来自man sed
:
标签
如果s ///自上次输入后已成功完成替换 从最后的t或T命令读取行,然后分支到标签;如果省略label,则跳转到脚本结尾。
答案 2 :(得分:1)
使用awk我们可以这样做
awk '{while(i<2){gsub(",,",",||,");i++}}1' temp.txt