从csv文件中仅删除* some * fullstops

时间:2016-04-17 08:44:30

标签: bash perl sed tr

如果我有如下行:

1,987372,987372,C,T,.,.,.,.,.,.,.,.,1,D,.,.,.,.,.,.,.,1.293,12.23,0.989,0.973,D,.,.,.,.,0.253,0,4.08,0.917,1.048,1.000,1.000,12.998
1,987393,987393,C,T,.,.,.,.,.,.,.,.,1,D,.,.,.,.,.,.,0.152,1.980,16.09,0.999,0.982,D,-0.493,T,0.335,T,0.696,0,5.06,0.871,0.935,0.998,0.997,16.252

如何使用,.,

替换,?,的所有实例

我想在数字中保留实际小数位,这样我才能做到

sed 's/./?/g' file

然而在做的时候:

sed 's/,.,/,?,/g' file

这似乎只在某些情况下起作用。即仍然存在,.,的情况。

任何人都有任何指示?

由于

5 个答案:

答案 0 :(得分:3)

这应该有效:

sed ':a;s/,\.,/,?,/g;ta' file

使用连续的,.,字符串,在替换成功后,要处理的下一个字符将是以下与模式不匹配的.,因此您需要第二次传递。< / p>

:a是即将推出的循环的标签

,\.,将匹配逗号之间的点。请注意,必须转义该点,因为.用于匹配任何字符(,a,将与,.,匹配)。

g用于一般替换

ta测试之前的替换,如果成功,则循环到:a标签以保留替换。

答案 1 :(得分:2)

使用sed可以通过运行一个循环来实现,如上面的答案所示,但使用带有外观的perl命令行可以轻松解决问题:

perl -pe 's/(?<=,)\.(?=,)/?/g' file

1,987372,987372,C,T,?,?,?,?,?,?,?,?,1,D,?,?,?,?,?,?,?,1.293,12.23,0.989,0.973,D,?,?,?,?,0.253,0,4.08,0.917,1.048,1.000,1.000,12.998
1,987393,987393,C,T,?,?,?,?,?,?,?,?,1,D,?,?,?,?,?,?,0.152,1.980,16.09,0.999,0.982,D,-0.493,T,0.335,T,0.696,0,5.06,0.871,0.935,0.998,0.997,16.252

这个命令不需要循环,因为我们不是匹配周围的逗号,而是使用lookbehind和lookahead来断言它们的位置。

答案 2 :(得分:1)

所有必要的是一次替换

$ perl -pe 's/,\.(?=,)/,?/g' dots.csv
1,987372,987372,C,T,?,?,?,?,?,?,?,?,1,D,?,?,?,?,?,?,?,1.293,12.23,0.989,0.973,D,?,?,?,?,0.253,0,4.08,0.917,1.048,1.000,1.000,12.998
1,987393,987393,C,T,?,?,?,?,?,?,?,?,1,D,?,?,?,?,?,?,0.152,1.980,16.09,0.999,0.982,D,-0.493,T,0.335,T,0.696,0,5.06,0.871,0.935,0.998,0.997,16.252

答案 3 :(得分:0)

您有一个使用sed样式正则表达式的示例。我将提供一个替代方案 - 解析CSV,然后将每个事物视为“字段”:

#!/usr/bin/perl

use strict;
use warnings;

#iterate input row by row
while ( <DATA> ) { 
   #remove linefeeds
   chomp;
   #split this row on ,
   my @row = split /,/;
   #iterate each field  
   foreach my $field ( @row ) {
       #replace this field with "?" if it's "."
       $field = "?" if $field eq ".";
   }
   #stick this row together again. 
   print join ",", @row,"\n";
}

__DATA__
1,987372,987372,C,T,.,.,.,.,.,.,.,.,1,D,.,.,.,.,.,.,.,1.293,12.23,0.989,0.973,D,.,.,.,.,0.253,0,4.08,0.917,1.048,1.000,1.000,12.998
1,987393,987393,C,T,.,.,.,.,.,.,.,.,1,D,.,.,.,.,.,.,0.152,1.980,16.09,0.999,0.982,D,-0.493,T,0.335,T,0.696,0,5.06,0.871,0.935,0.998,0.997,16.252

为了说明这个概念,这比它需要的更冗长。这可以减少到:

perl -F, -lane 'print join ",", map { $_ eq "." ? "?" : $_ } @F'

如果您的CSV也有引号,那么您可以打开Text::CSV模块,该模块可以整齐地处理。

答案 4 :(得分:0)

您只需要2次通过,因为在if(is_stopped(pid)) {} if(is_stopped(pid)) {} 匹配项上找到的结尾,无法与下一个,.,上的前导,匹配:< / p>

,.,

以上内容适用于任何操作系统上的任何sed。