如何将引号中的多行数据重新组合成一行?

时间:2014-01-04 07:59:36

标签: regex bash csv sed awk

您好我有一个csv文件,看起来像这样。请注意,并非所有数据都是多行的!

225253;abc;def;ghi;"- sometext 
- sometext
- 3sometext
";asd,asd;58.2500;False;False;False;17;0.0000;; 

我的目标是使用bash脚本将其转换为以下形式:

225253;abc;def;ghi;"- sometext - sometext - 3sometext";asd,asd;58.2500;False;False;False;17;0.0000;;

我的第一个猜测就是这个。但不知怎的,它不会起作用......

sed -e 's/\"\([^"]+\)\"//g'

5 个答案:

答案 0 :(得分:1)

执行此操作的干净方法是使用Text::CSV,注释中建议的@JonathanLeffler或类似的内容。也就是说,使用专用于处理CSV文件的库。请参阅底部的Perl实现。

但是,默认情况下通常不会安装Text::CSV,因此您可能必须自己安装它。如果这不是一个选项或者对你来说太难,那么一个不太完美但更简单的awk解决方案可能已经足够好了,基于similar question

awk -F ";" -v nf=13 'NF < nf { line = line (line ? OFS : "") $0; fields += NF } fields >= nf { print line; line=""; fields=0 } NF == nf'

供参考,使用Text::CSV

的Perl解决方案
use Text::CSV;

my $sep = ';';
my $csv = Text::CSV->new({ binary => 1, sep_char => $sep });

while (my $row = $csv->getline(*STDIN)) {
    print join($sep, map { s/\n$//; s/ *\n/ /g; $_ } @$row), "\n";
}

将其保存在文件transform-csv.pl中并使用以下命令运行:

perl transform-csv.pl < sample.csv

答案 1 :(得分:1)

这可能适合你(GNU sed):

sed -r ':a;/^[^"]*("[^"]*")+(;[^"]+|$)/b;$!{N;s/\n//;ba}' file

这会查找具有匹配引号的行。如果它找到一条带有不匹配引号的行,则会附加下一行,删除换行符并重复,直到引号匹配或到达文件末尾。

N.B。这不符合引号内的报价。

答案 2 :(得分:0)

perl -MText::CSV_XS -e'my $csv = Text::CSV_XS->new({binary=>1,sep_char=>";"});while(my $row = $csv->getline(ARGV)){$csv->print(STDOUT,[map s/\n/ /g,@$row])}'

或者您也可以使用Text::CSV。将参数添加到解析器构造函数以调整其他行为。

答案 3 :(得分:0)

awk '{gsub(/\n/,"")}1' FS=";" RS=";" ORS=";" file

给出

225253;abc;def;ghi;"- sometext - sometext- sometext";asd,asd;58.2500;False;False;False;17;0.0000;;

<强>更新

或在Gnu Awk第4版中使用patsplit

BEGIN { FS=RS=";"}
{
    if (patsplit($0,a,/"[^"]+"/,s)) {
        gsub(/\n/,"",a[1])
        printf "%s%s%s", s[0],a[1],s[1]
    }
    else
        printf "%s", $0
    printf ";"
}

这只会删除双引号内的换行符。

答案 4 :(得分:0)

也可以试试这个sed脚本。它匹配在行结束前具有开放双引号"而没有字段分隔符;的行。假设只有当它们出现在双引号字段中时才需要删除换行符。它还假设引用整个字段(至少结束像"stuff";)。如果情况并非如此,则应进行微调。

:again
/"[^;]*$/ {
  N
  s/\n//
  b again
}
s/"[^;]*";/;/g

将其放入script.sed并按sed -r -f script.sed file

运行

如果保留引用字段,则只需从脚本中删除最后一行。