如何替换不在特定字符之后的换行符?

时间:2018-03-15 18:18:19

标签: regex perl awk sed

我需要处理一个csv文件,但其中一个字段包含换行符。

如何用空格替换不在双引号字符(“)之后的所有换行符?任何带有awk,perl,sed等的解决方案都是可以接受的。

表格中的文件:

497,50,2008-08-02T16:56:53Z,469,4,"foo bar foo  bar"
518,153,2008-08-02T17:42:28Z,469,2,"foo bar bar"

所需的输出是:

#outer{
    display: flex;
}
#inner{
    margin: auto;
}

3 个答案:

答案 0 :(得分:2)

我理解您的问题是替换字段内换行符的请求(即使它们在"之后立即发生,例如在包含␊foofoo "bar"␊baz的字段中。以下内容实现了:

use Text::CSV_XS qw( );

my $qfn_in  = ...;
my $qfn_out = ...;

open(my $fh_in,  '<', $qfn_in)  or die("Can't open \"$qfn_in\": $!\n");
open(my $fh_out, '>', $qfn_out) or die("Can't create \"$qfn_out\": $!\n");

my $csv = Text::CSV_XS->new({ binary => 1, auto_diag => 2 });
while ( my $row = $csv->getline($fh_in) ) {
   s/\n/ /g for @$row;
   $csv->say($fh_out, $row);
}

我认为使用以下内容会更有意义:

for (@$row) {
   s/^\s+//;   # Remove leading whitespace.
   s/\s+\z//;  # Remove trailing whitespace.
   s/\s+/ /g;  # Replaces whitespace with a single space.
}

答案 1 :(得分:0)

你可以试试这个sed但是这个问题不够清楚,知道怎么处理像

这样的行
497,50,2008-08-02T16:56:53Z,469,4,"truc biz",test

sed ':A;/[^"]$/{N;bA};y/\n/ /' infile

答案 2 :(得分:0)

很容易匹配csv中的字段。

框架是引用/未引用字段之间的内容 并且是分隔符或记录标记的结尾。

因此框架也匹配以验证字段 这样做之后,只需更换引用字段中的换行符即可 这可以在回电中完成。

正则表达式((?:^|,|\r?\n)[^\S\r\n]*)(?:("[^"\\]*(?:\\[\S\s][^"\\]*)*"[^\S\r\n]*(?=$|,|\r?\n))|([^,\r\n]*(?=$|,|\r?\n)))

这是Perl中的所有内容。

use strict;
use warnings;

$/ = undef;

sub RmvNLs {
   my ($delim, $quote, $non_quote) = @_;
   if ( defined $non_quote ) {
      return $delim . $non_quote;
   }
   $quote =~ s/\s*\r?\n/ /g;
   return $delim . $quote;
}

my $csv = <DATA>;

$csv =~ s/
     (                                  # (1 start), Delimiter (BOS, comma or newline)
          (?: ^ | , | \r? \n )
          [^\S\r\n]*                         # Leading optional horizontal whitespaces
     )                                  # (1 end)
     (?:
          (                                  # (2 start), Quoted string field
               "                                  # Quoted string
               [^"\\]* 
               (?: \\ [\S\s] [^"\\]* )*
               "
               [^\S\r\n]*                         # Trailing optional horizontal whitespaces
               (?= $ | , | \r? \n )               # Delimiter ahead (EOS, comma or newline)
          )                                  # (2 end)
       |                                   # OR
          (                                  # (3 start), Non quoted field
               [^,\r\n]*                          # Not comma or newline
               (?= $ | , | \r? \n )               # Delimiter ahead (EOS, comma or newline)
          )                                  # (3 end)
     )
   /RmvNLs($1,$2,$3)/xeg;

print $csv;


__DATA__
497,50,2008-08-02T16:56:53Z,469,4,"foo bar 
foo



bar"
518,153,2008-08-02T17:42:28Z,469,2,"foo bar
bar"

输出

497,50,2008-08-02T16:56:53Z,469,4,"foo bar foo bar"
518,153,2008-08-02T17:42:28Z,469,2,"foo bar bar"