使用sed从CSV文件中的带引号数字中移除千位分隔符逗号。

4

我的 sed 技能不是很好,所以我不确定如何处理这样一行文本

1,2,"12,345",x,y,"a,b"

把它转化为
1,2,12345,x,y,"a,b"

因此,数字"12,345"变成了12345,但"a,b"保持不变。

如果数值是数字,我需要以某种方式保留逗号周围的值。我有一个想法,关于如何只处理数字,但不确定如何仅删除逗号,而不是整列。


尝试操作特定形式的数据是在自找麻烦。解析数据,清理它,并将其写回。请参见下面的Perl解决方案之一。 - Andy Lester
5个回答

2
解析 CSV 应使用适当的 CSV 解析器。我也会推荐使用 perl
perl -MText::ParseWords -ne '
    @line = parse_line(",", 1, $_); 
    print join "," , map { s/,//g if $_ =~ /^[0-9,"]+$/; $_ } @line
' text.csv

测试:

$ cat text.csv
1,2,"12,345",x,y,"a,b"
"a,c","12,345",x,y,"a,b"

$ perl -MText::ParseWords -ne '
    @line = parse_line(",", 1, $_);
    print join "," , map { s/,//g if $_ =~ /^[0-9,"]+$/; $_ } @line
' text.csv
1,2,"12345",x,y,"a,b"
"a,c","12345",x,y,"a,b"

To make in-place changes you can use -i option or re-direct the output to another file.


1
Perl解决方案,使用Text::CSV

#!/usr/bin/perl
use warnings;
use strict;

use Text::CSV;

my @rows;

my $csv = 'Text::CSV'->new({ binary => 1}) or die 'Text::CVS'->error_diag;
open my $IN, '<', 'file.csv' or die $!;
while (my $row = $csv->getline($IN)) {
    for my $cell (@$row) {
        $cell =~ s/,// if $cell =~ /^[0-9,]+$/;
    }
    push @rows, $row;
}
$csv->eof or $csv->error_diag;

open my $OUT, '>', 'new.csv' or die $!;
$csv->print($OUT, $_) for @rows;
close $OUT or die $!;

1

在一个正则表达式替换中,你可以做一些像这样恶心的事情:

/\G(?|(")(\d+)(?:,(\d+))*(")|()([^,]+)()())(,|$)/g

用以下内容替换:

\1\2\3\4\5

这应该在Perl中可以很好地工作。

演示:http://regex101.com/r/kQ5fU1


0

您可以使用:

echo '1,2,"12,345",x,y,"a,b"' | sed 's/"\([0-9]*\),\([0-9]*\)"/\1\2/g'

编辑:实际上,我的解决方案仅在双引号之间只有一个逗号的情况下有效。


最多会有两个逗号,所以sed 's/"([0-9]+),([0-9]+)(,([0-9]+)){0-1}"/\1\2\3/g'是否正确? - MrSilverSnorkel

0
使用这个模式(\d),(\d)(?!(([^"]*"){2})*[^"]*$),并用$1$2进行替换
演示

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接