我想删除CSV文件中双引号之间的所有非法换行符LF。
"name", "created"
"David A","2022-04-04"
"Mark
B", "2022-04-09"
"Peter C", "2022-05-01"
文件名为name.csv
,例如
现在我可以用
cat name.csv |
| perl -p -e 's/n/!LF_SYMBOL!/g'
| perl -p -e 's/"!LF_SYMBOL!"/"!EOL!"/g'
| perl -p -e 's/!LF_SYMBOL!//g'
| perl -p -e 's/!EOL!/n/g'
> name_new.csv
但是它很丑。我想删除双引号以外的所有换行符
我试过了
perl -p -e 's/[^"]n//' name.csv
和
perl -p -e 's/^[^"]n//' name.csv
由于某种原因,都只是移除所有的"n
。
任何想法?
通常最好使用现有的解析器,而不是编写自己的解析器。这也不例外。
[1]如果提供了allow_whitespace => 1
,它甚至可以容忍逗号后面的空格
所以我会使用这个模块,而不是编写我自己的解析器。
你只需要:
perl -MText::CSV_XS=csv -e'
csv
in => *ARGV,
allow_whitespace => 1,
on_in => sub { s/n//g for @{ $_[1] }; };
' name.csv >name_new.csv
输出:
name,created
"David A",2022-04-04
MarkB,2022-04-09
"Peter C",2022-05-01
如果出于某种原因你想要避免XS,较慢的Text::CSV是一个直接的替代品。
- 处理字段换行需要传递
binary => 1
,这是使用csv
函数时的默认值。
如果这是一个有效的CSV文件,则使用库读取它,如Text::CSV。他们没有在字段中嵌入换行符的问题,然后很容易删除那些
use warnings;
use strict;
use feature 'say';
use Text::CSV;
my $file = shift or die "Usage: $0 file.csvn";
my $csv = Text::CSV->new(
{ binary => 1, auto_diag => 1, allow_whitespace => 1 });
open my $fh, '<', $file or die "Can't open $file: $!";
while (my $row = $csv->getline($fh)) {
s/n+//g for @$row;
$csv->say(*STDOUT, $row);
}
这也可以在一行代码中完成,如果有一些好处的话。
发布的文本,因为它的存在,不是有效的CSV,不能被库直接解析,因为字段之间缺少逗号。我想这些都是拼写错误,因为问题是"csv";在很多地方。请澄清。
嵌入的换行符被binary
属性接受,而逗号后的额外空格(严格无效)被allow_whitespace
属性接受。
由于您有一个两列"CSV"类文件,并且您想要的只是删除两个字段内的换行符,因此您可以使用像
这样的解决方案perl -0777 -i -pe 's/^("[^"]*(?:""[^"]*)*")s*,s*(?1)$/$&=~s!R+!!gr/gme' file.csv
查看主正则表达式演示。当找到匹配时,第二个正则表达式s!R+!!gr
删除匹配中的所有换行符。
细节:
^
-行开始(由于m
标志)("[^"]*(?:""[^"]*)*")
-组1:"
,除"
以外的零个或多个字符,然后是""
的零个或多个重复,然后是"
以外的零个或多个字符,然后是"
(匹配文本双引号用"
转义的CSV字段)s*,s*
-逗号,其中包含0个或多个空格(?1)
—重复组1模式的子程序$
-行结束(由于m
标志)。