我的CSV看起来如下:
A,01,ALPHA
00,D,CHARLIE
E,F,02
这是转换后所需的文件:
"A",01,"ALPHA"
00,"D","CHARLIE"
"E","F",02
如您所见,完全数字的字段不加引号,而引用alpha(或字母数字)。
在Perl中解决这个问题的合理方法是什么?
下面已经评论过了,但我已尝试过像
这样的内容perl -pe 's/(\w+)/"$1"/g'
这并不起作用,因为\ w显然会接受数字。
答案 0 :(得分:5)
我建议不要重新发明轮子,而是像zdim推荐的那样使用现有的模块。以下是使用Text::CSV_XS
的示例<强> test.pl 强>
#!/usr/bin/env perl
use warnings;
use strict;
use Text::CSV_XS;
use Scalar::Util qw( looks_like_number );
my $csv = Text::CSV_XS->new();
while (my $row = $csv->getline(*STDIN)) {
my @quoted_row = map { looks_like_number($_) ? $_ : '"'. $_ .'"' } @$row;
print join(',',@quoted_row) . "\n";
}
<强>输出强>
cat input | perl test.pl
"A",01,"ALPHA"
00,"D","CHARLIE"
"E","F",02
答案 1 :(得分:1)
好像你是在追逐一个班轮。这是一个基本的
perl -lpe '$_ = join ",", map /^\d+$/ ? $_ : "\"$_\"", split ",";' input.csv
按,
拆分每一行,并将获得的列表传递给map
。每个元素仅针对仅数字/^\d+$/
进行测试并且不受影响地传递,否则使用"
填充。然后map
返回,
的返回。
-l
删除换行符,自"
填充整行后需要的内容。结果已分配回$_
,以便能够使用-p
,因此无需显式打印。
如果你不坚持使用单行代码,代码很容易在脚本中使用。
模块可以更好地处理csv文件,例如Text::CSV
答案 2 :(得分:1)
修改了另一个单行输入文件以添加带字母数字字段的行
$ cat ip.csv
A,01,ALPHA
00,D,CHARLIE
E,F,02
23,AB12,53C
$ perl -F, -lane 's/.*[^0-9].*/"$&"/ foreach(@F); print join ",", @F' ip.csv
"A",01,"ALPHA"
00,"D","CHARLIE"
"E","F",02
23,"AB12","53C"
要修改OP的尝试:
$ perl -pe 's/(^|,)\K\d+(?=,|$)(*SKIP)(*F)|\w+/"$&"/g' ip.csv
"A",01,"ALPHA"
00,"D","CHARLIE"
"E","F",02
23,"AB12","53C"
(^|,)\K\d+(?=,|$)(*SKIP)(*F)
这将跳过仅包含数字的字段,替换模式\w+
将被替换