perl -i -pe 's/(,\h*"[^\n"]*)\n/$1 /g' /opt/data-integration/transfer/events/processing/Master_Events_List.csv
这是怎么回事?我尝试过翻译,但是有点模糊。可能会在这里返回哪些示例?
答案 0 :(得分:3)
首先,请勿尝试使用正则表达式来操作CSV(或XML或HTML)。尽管CSV看起来很简单,但它可能很微妙。而是使用Text::CSV。例外是,如果您的CSV格式不正确,并且您正在对其进行修复。
现在,对于您的正则表达式正在做什么。首先,让我们将其从s//
转换为s{}{}
,这在眼睛上会更容易一些,并使用\x
,这样我们就可以将内容隔开一些。
s{
# Capture to $1
(
# A comma.
,
# 0 or more `h` "horizontal whitespace": tabs and spaces
\h*
# A quote.
"
# 0 or more of anything which is not a quote or newline.
[^\n"]*
)
# A newline (not captured)
\n
}
# Put the captured bit in with a space after it.
# The `g` says to do it multiple times over the whole string.
{$1 }gx
它将foo, "bar\n
更改为foo, "bar
。我猜测这会将CSV中带有换行符的文本字段变成只有空格的文本字段。
foo, "first
field", "second
field"
将成为
foo, "first field", "second field"
使用Text :: CSV可以更好地处理此问题。我怀疑转换的目的是帮助无法处理换行符的CSV解析器。 Text::CSV can with a little coercing。
#!/usr/bin/env perl
use strict;
use warnings;
use v5.10;
use autodie;
use Text::CSV;
use IO::Scalar;
use Data::Dumper;
# Pretend our scalar is an IO object so we can use `getline`.
my $str = qq[foo, "bar", "this\nthat"\n];
my $io = IO::Scalar->new(\$str);
# Configure Text::CSV
my $csv = Text::CSV->new({
# Embedded newlines normally aren't allowed, this tells Text::CSV to
# treat the content as binary instead.
binary=> 1,
# Allow spaces between the cells.
allow_whitespace => 1
});
# Use Text::CSV->getline() to do the parsing.
while( my $row = $csv->getline($io) ) {
# Dump the contents of the row
say Dumper $row;
}
它将正确解析该行及其嵌入的换行符。
$VAR1 = [
'foo',
'bar',
'this
that'
];
答案 1 :(得分:0)
将此内容编辑为第二本Schwern(也被赞成):正则表达式似乎不适合处理CSV。
对于正则表达式,让我们对其进行剖析。从顶层开始:
's/(,\h*"[^\n"]*)\n/$1 /g'
s/part1/part2/g
表示“将第一部分替换为第二部分”。
现在让我们检查“第一部分”:
(,\h*"[^\n"]*)\n
括号括起一个组。只有一个组,所以它成为组号1。我们将在下一步继续讨论。
然后,检查https://perldoc.perl.org/perlrebackslash.html以获取字符类的解释。 \h
是水平空格,\n
是逻辑换行符。
该组中的表达式表示:“以逗号开头,然后是任意数量的水平空白字符,然后是除换行符和引号之外的任何内容;最后,必须有尾随的换行符”。因此,它基本上是由csv字段引起的逗号。
最后,“第二部分”显示为:
$1
这只是对前面捕获的组号1的引用,后跟一个空格。
总体而言,整个表达式将替换不以引号终止的尾随字符串字段,并删除其换行符。
答案 2 :(得分:0)
在被伪装成记录结尾的引用字段中修复换行符的最佳方法:
首先,请勿尝试通过模块操作CSV(或XML或HTML)。尽管CSV似乎有些棘手,但它却非常简单。不要使用Text :: CSV。而是将替代正则表达式与回调一起使用。
此外,您可以使用正则表达式来正确地解析一个CSV而不替换
换行符,但您可能希望使用Perl对其进行修复以便用于其他某种语言。
正则表达式(带有修饰符)
(id1, id2, date)
解释
/((?:^|,|\r?\n))\s*(?:("[^"\\]*(?:\\[\S\s][^"\\]*)*"[^\S\r\n]*(?=$|,|\r?\n))|([^,\r\n]*(?=$|,|\r?\n)))/
(注意-这需要一个脚本。)
Perl示例
( # (1 start), Delimiter (comma or newline)
(?: ^ | , | \r? \n )
) # (1 end)
\s* # Leading optional whitespaces ( this is for trim )
# ( if no trim is desired, remove this, add
# [^\S\r\n]* to end of group 1 )
(?:
( # (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)
)
输出
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 (comma or newline)
(?: ^ | , | \r? \n )
) # (1 end)
\s* # Leading optional whitespaces ( this is for trim )
# ( if no trim is desired, remove this, add [^\S\r\n]* to end of group 1 )
(?:
( # (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"
hello
world
"asdfas"
ID,NAME,TITLE,DESCRIPTION,,
PRO1234,"JOHN SMITH",ENGINEER,"JOHN HAS BEEN WORKING
HARD ON BEING A GOOD
SERVENT."
PRO1235, "KEITH SMITH",ENGINEER,"keith has been working
hard on being a good
servent."
PRO1235,"KENNY SMITH",,"keith has been working
hard on being a good
servent."
PRO1235,"RICK SMITH",,, #