Regex 删除假逗号
一个白痴客户正在生成csv文件,但有一个字段有时在(描述字段)中有额外的逗号 是否有一个整洁的正则表达式来查找这些坏记录并用其他内容替换多余的逗号。SED命令行就可以了 例如:Regex 删除假逗号,regex,csv,perl,Regex,Csv,Perl,一个白痴客户正在生成csv文件,但有一个字段有时在(描述字段)中有额外的逗号 是否有一个整洁的正则表达式来查找这些坏记录并用其他内容替换多余的逗号。SED命令行就可以了 例如: A,B,C,This is a description,D,E F,G,H,This is a description with a comma (,) in it,D,E 我需要一个SED,它可以告诉我行中有太多的逗号,并从字段4中删除多余的逗号 我们没有权利告诉愚蠢的客户更改他们的代码 已添加 我不反对只删除一个我
A,B,C,This is a description,D,E
F,G,H,This is a description with a comma (,) in it,D,E
我需要一个SED,它可以告诉我行中有太多的逗号,并从字段4中删除多余的逗号
我们没有权利告诉愚蠢的客户更改他们的代码
已添加
我不反对只删除一个我必须多次运行的伪逗号的解决方案。我试图用sed解决这个问题,但无法在匹配组内执行替换。取而代之的是,我设法用一个可以从终端运行的ruby one liner实现了这一点:
cat your_file | ruby -ne '$_.scan(/^(\w+,\w+,\w+,)([^$]+)(,\w,\w)$/).each{|m|puts m[0]+m[1].gsub(",","")+m[2]}'
这假设始终有6列,第4列可能包含逗号
代码已经用ruby 1.8.7、1.9.1和2.1.0进行了测试。我的方法是根据总列数计算要删除的逗号以及要修改的列。它接受三个参数:输入文件、总列数和带有额外逗号的怪异列 下一个脚本执行一些计算。当存在额外的逗号时,会有额外的列,所以它会找到这些额外列的位置并将它们连接起来
#!/usr/bin/env perl
use warnings;
use strict;
use Text::CSV_XS;
my (@columns);
open my $fh, '<', shift or die;
my ($total_columns, $weird_column) = (shift, shift);
my $csv = Text::CSV_XS->new or die;
while ( my $row = $csv->getline( $fh ) ) {
undef @columns;
if ( @$row == $total_columns ) {
@columns = @$row;
next;
}
my $extra_columns = @$row - $total_columns;
my $post_columns_index = $weird_column + $extra_columns;
@columns = (
@$row[0..($weird_column-2)],
join( '', @$row[($weird_column-1)..($post_columns_index-1)]),
@$row[$post_columns_index..$#$row]
);
}
continue {
$csv->print( \*STDOUT, \@columns );
printf "\n";
}
像这样运行:
perl script.pl infile 6 4
这将产生:
A,B,C,"This is a description",D,E
F,G,H,"This is a description with a comma () in it",D,E
F,G,H,"This is a description with two commas () in it",D,E
F,G,H,"This is a description with three commas () in it",D,E
可能它会在边缘情况下失败(第一个和最后一个字段)。我没有对它进行深入的测试,但我希望你能理解。我试着尽可能一般地做。解决方案1:单行,删除,
这是一个SED单行程序:
sed -r 's/([^,],[^,],[^,],)(.*)(,.+,.+)/\1'"$(sed -r 's/([^,],[^,],[^,],)(.*)(,.+,.+)/\2/' <<< $myInput | sed 's/,//g')"'\3/' <<< $myInput
它为我们捕获字符串的第一部分(F,G,H,
),第二部分(*
)和最后一部分(,D,E
)
第一个和第三个捕获基团将保持不变,而第二个将被取代。对于替换,我们第二次(实际上是第三次)调用
sed
。首先,我们只捕获第二个组,其次,我们将每个,
替换为零(仅在捕获组中!)
证明:
当然,如果没有多余的逗号,则不会替换任何内容:
解决方案2:整个文件,逐行删除
,
如果只想指定一个文件,则应为可使用的文件的每一行进行替换
while read line; do sed -r 's/([^,],[^,],[^,],)(.*)(,.+,.+)/\1'"$(sed -r 's/([^,],[^,],[^,],)(.*)(,.+,.+)/\2/' <<< $line | sed 's/,//g')"'\3/' <<< $line; done < input.txt
我们还有三个俘虏小组。这使我们可以简单地将第二个组包装在“
中
如果列计数是固定的,我们可以尝试用lookaheads
?:
切掉前三列和最后两列,并在行的其余部分(这是描述)中匹配逗号。我得到了如下结果:
(?:^(?:[^,]*,){3})(?:(?:[^,]*(,))*[^,]*)(?:(?:,[^,]*){2}$)
[^,]*
是字段(不带逗号),因此(?:^(?:[^,]*,){3})
将剪切前3列(包括以下逗号)。(?:(?:,[^,[^,]*){2}$)
将删除最后2列,包括尾随逗号。(?:(?:(?:,[^,]*,)*,)*[^,]*))
与内部匹配
在JavaScript中,整个表达式返回完整的描述(带逗号)作为第一个匹配项,其中的逗号作为第二个匹配项。根据正则表达式引擎的不同,它可以使用espace和replace来替换描述(如果引擎给出匹配表达式的范围)或将(,)
表达式匹配逗号和替换语法
我现在不可能用sed运行和测试,但是regex应该非常接近您需要的解决方案。两个问题:每行是否有固定数量的字段?哪些字段可以有额外的逗号?我猜测您不能将分隔符更改为管道或其他东西?因为老实说,对于逗号不是不可更改的。@Birei-是的,每行中有固定数量的字段。假设现在只有一个字段可以有额外的逗号,但如果您可以调整,那么您将得到+1或更多。@Jonathan-您是正确的-我们不能更改文件格式。我们只能对文件进行后期处理。我们不会删除逗号,而是最好用引号避开描述:。这将需要编写一些bash脚本逐行处理文件。我将不得不等待其他人对这是否好的投票-我没有访问Ruby的权限。任何其他免费的s&r工具都可以接受-我使用了很多,所以grep或任何其他免费工具都可以。@OldCurmudgeon我会把答案留在这里,它可能会对某人有所帮助。我记得几年前也遇到过同样的问题。我尝试了
(^(?:[^,]*?,){3})(.*?,((?:,[^,[^,]*){2})<代码> >代码> $$ 1 $ 2 $ 3 $ 4 /代码>这几乎是你所拥有的。它在开始时剥离<代码> n< /代码>列,然后需要<代码> xxx,yyy >结尾>代码> m < /c>列。然后将它放在一起,将逗号放在中间。遗憾的是,它似乎不一致。我最喜欢你的解决方案3。我可以使用等效的<代码>。((?:[^,],){3})(.*)((?:,.*){2})
在TextCrawler
中,它似乎工作得很好。@OldCurmudgeon当然,最终使用哪个正则表达式取决于您,但据我所知sed
不支持非捕获组,所以在使用sed
时,我尽量少分组。
while read line; do sed -r 's/([^,],[^,],[^,],)(.*)(,.+,.+)/\1'"$(sed -r 's/([^,],[^,],[^,],)(.*)(,.+,.+)/\2/' <<< $line | sed 's/,//g')"'\3/' <<< $line; done < input.txt
sed -r 's/([^,],[^,],[^,],)(.*)(,.*,.*)/\1"\2"\3/' input.txt
(?:^(?:[^,]*,){3})(?:(?:[^,]*(,))*[^,]*)(?:(?:,[^,]*){2}$)