仅替换特定列中的字符(CSV)

时间:2015-06-01 16:09:41

标签: linux csv awk sed

我有这样的数据:

1;2015-04-10;23:10:00;10.4.2015 23:10;8.9;1007.5;0.3;0.0;0;55
2;2015-04-10;23:20:00;10.4.2015 23:20;8.6;1007.8;0.4;0.0;0;56
3;2015-04-10;23:30:00;10.4.2015 23:30;8.5;1008.1;0.4;0.0;0;57

它有点.作为小数点分隔符,但我需要使用,代替。

所需数据:

1;2015-04-10;23:10:00;10.4.2015 23:10;8,9;1007,5;0,3;0,0;0;55

我尝试使用Sed。使用sed -i 's/\./,/g' myfile.csv我可以用逗号替换所有点,但会破坏第四列上的日期。如何在其他地方将点​​更改为逗号,但保留第四列原样?如果其他Linux工具比Sed更适合此任务,我也可以使用它。

4 个答案:

答案 0 :(得分:5)

sed用于简单替换,对于任何其他只使用awk:

$ awk 'BEGIN{FS=OFS=";"} {for (i=5;i<=NF;i++) sub(/\./,",",$i)} 1' file
1;2015-04-10;23:10:00;10.4.2015 23:10;8,9;1007,5;0,3;0,0;0;55
2;2015-04-10;23:20:00;10.4.2015 23:20;8,6;1007,8;0,4;0,0;0;56
3;2015-04-10;23:30:00;10.4.2015 23:30;8,5;1008,1;0,4;0,0;0;57

答案 1 :(得分:0)

Perl和Text::CSV

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

use Text::CSV;

my $csv = 'Text::CSV'->new({ binary      => 1,
                             sep_char    => ';',
                             quote_space => 0,
                           }) or die 'Text::CSV'->error_diag;
open my $FH, '<:encoding(utf8)', 'input.csv' or die $!;
$csv->eol("\n");
while (my $row = $csv->getline($FH)) {
    s/\./,/g for @$row[ 0 .. 2, 4 .. $#$row ];
    $csv->print(*STDOUT, $row);
}

答案 2 :(得分:0)

你可以选择:

awk 'BEGIN {FS=OFS=";"} {if(NF==5);gsub(/\./,",",$5)} 1 ' filename

我在这里使用gsub代替sub;区别在于sub将仅替换第一次出现,而gsub将替换所有出现次数。

答案 3 :(得分:0)

在第二列中将点更改为逗号

awk '{gsub(/\./,",",$2)}1' file

1;2015-04-10;23:10:00;10.4.2015 23:10;8,9;1007,5;0,3;0,0;0;55
2;2015-04-10;23:20:00;10.4.2015 23:20;8,6;1007,8;0,4;0,0;0;56
3;2015-04-10;23:30:00;10.4.2015 23:30;8,5;1008,1;0,4;0,0;0;57