2016-09-03 43 views
1

我想用一个句号后面有一个空格替换一个CSV的标题场(场2)上了一个句号:用sed来代替句号与句号后面空间

CSV例如:

8389383, hello my.friend,839083083,3390903 

预期输出:

8389383, hello my. friend,839083083,3390903 

我可以成功地取代了一个句号的CSV与空间只能用这条线:

sed -r ':b s/^([^,]*,[^,]*)\./\1 /g; t b' csv 

但是,我想用句号替换句号,后面跟一个空格。我试过了:

sed -r ':b s/^([^,]*,[^,]*)\./\1. /g; t b' csv 

但是这个挂起并且不会产生结果。

什么可以添加到该行以允许这?

编辑 - 只需要添加,我想替换的字段2(标题字段)中可能会有多个句点。我也不希望这条规则适用于csv中的任何其他字段。

+0

不妨加样品输入/输出,更好地反映您的要求,以便其他人可以轻松地测试:) – Sundeep

+3

一点也没有不要停下来,因为在完全停止之后还没有完成数十亿上千亿的空间。当它第一次匹配时,它添加一个空白;这个测试是真实的,所以它回来了,再次尝试,发现一个停止,增加一个空白,并且......在一段时间后它变得无聊。您可能需要在停止后留出一些尾随上下文 - 非空白。 –

回答

5

awk是最适合这些类型的工作岗位

对于更换所有全停在第二场就

awk -v FS="," -v OFS="," '{gsub(/\./,". ",$2)}1' file.csv > tmpfile && mv tmpfile file.csv 

8389383, hello my. friend,839083083,3390903 
8389383, hello my. fri. end,839083083,3390903 
+2

awk在这里似乎是最好的选择,因为我们可以有选择地将'g'标志应用于第二个字段 – Sundeep

+0

@spasic您是否指定了'gensub'。你可能知道'sub'和'gsub'都没有。不过,使用'gensub'可以减少脚本的移植性。 – sjsam

+0

@sjsam好吧,这看起来可能会有所斩获,但首先 - 我不太熟悉awk,它能以类似于'sed -i'的方式直接将结果呈现给文件吗? – neilH

1

如何:

sed -i -e 's/^\([^,]*,[^.,]*\)\.\([^,]*\)/\1. \2/' file.csv 

编辑如果你在现场有多个句号,你不能sed做到这一点。这里有一个perl一行代码,但:

perl -i -pe 'sub t {($s)[email protected]_; $s=~s/\./. /g; $s}; s/^[^,]*,\K([^,]*)/t($1)/e;' file.csv 

说明:随着s///命令,我们发现的第一个字段([^,]*,),我们跳过它(\K),然后我们找到第二个字段(([^,]*))。对于那个领域,我们执行功能t,它做一个简单的变电站。

+0

嗨,这只会取代这第一句句号。如果在第二个字段中有更多的字段,它似乎不会取代它们。 – neilH

+0

@ bms9nmh:使用'sed'确实很费力。 – sjsam

+0

@ bms9nmh对不起,我错过了你编辑的问题。我为我的答案添加了一个基于perl的解决方案。它不能用'sed'完成。 – redneb

0

这可能为你工作(GNU SED):

sed -r ':a;s/^([^,]*,[^,.]*)\./\1\n/;ta;s/\n/. /g' file 

这里的诀窍是把.变成something else(我赞成新因为它通过seds设计是唯一的),然后全局更改something elsewhatever作为线上的最后一个操作。

另一种方法是复制行,换一块,并用重组从复制的部分,你不希望更改线路:

sed -r 's/,/\n/;s/,/\n/;h;s/\./& /g;G;s/.*\n(.*)\n.*\n(.*)\n.*\n/\2,\1,/' file 
0
$ cat file.csv 
8389383, hello my.friend, 839083083, 3390903 
8389383, hello my.fri.end, 839083083, 3390903 

$ perl -i -F, -e '$F[1] =~ s/\./. /g; print join(",",@F)' file.csv 

$ cat file.csv 
8389383, hello my. friend, 839083083, 3390903 
8389383, hello my. fri. end, 839083083, 3390903 
  • -F,分割每行在,并将其保存在@F阵列中。 -F选项也隐式设置为-a-n。请参阅perldoc Command Switches以进一步阅读
  • join(",",@F)将阵列与,一起作为分隔符。不知道是否有Perl中的含蓄的方式来打印相同的输入分隔符修改后的数组