使用正则表达式更改CSV文件

时间:2015-02-24 15:18:22

标签: regex perl

因为我同时写了question, what got closed的答案 - 试图改写并重新提问。

拥有180个百万条记录的CSV文件,其中5列为:

"c a","L G-3 (8) N (4th G P Q C- 4 R- 1 T H- 15.6 I- W 8.1) (B)","C & P_L",1,0

如何将其更改为3列结构:

"c a|L G-3 (8) N (4th G P Q C- 4 R- 1 T H- 15.6 I- W 8.1) (B)|C & P_L",1,0

e.g。需要将列1,2,3与|连接起来并将其打印为一列并保持其他列不变

用正则表达式尝试:

cat RelatedKW.csv | perl -pe 's/(\|)/\//g'| perl -pe 's/("\s*"|"\s*"\s*\\n$)//g'| perl -pe 's/^,"|,,|"\s*,\s*\"/|/g' | perl -pe 's/\"(\d+),(\d+)\"/ |$1|$2/g' > newRKW4.csv`

这有更好的方法吗?

2 个答案:

答案 0 :(得分:1)

您通常应该避免使用正则表达式解析CSV,正如Kent Fredricanother similar question的回答中所解释的那样:

  

不使用CPAN确实是一种灾难。

     

在尝试编写自己的CSV实现之前,请考虑这一点。   Text :: CSV超过一百行代码,包括修复的bug和边缘情况,   从头开始重新编写这些内容只会让你了解CSV是多么糟糕。

尝试使用正则表达式解析CSV是真的不良做法,因为例如,您需要处理:

  • 转义引号
  • 转义分隔符
  • 包含分隔符的字段

等等,所有Text :: CSV都将为您处理。

这是一个使用Text :: CSV的解决方案。我不是Perl专家,所以下面的代码可能会遗漏一些东西,但它可能比使用正则表达式更好:

perl -MText::CSV_XS -E '$csv = Text::CSV_XS->new ({ eol => $/ }); $csv->print(*STDOUT, [join(q{|}, @$row[0..2]), @$row[3..4]]) while ($row = $csv->getline(*STDIN))' < csv

<强>输入:

"c a","L G-3 (8) N (4th G P Q C- 4 R- 1 T H- 15.6 I- W 8.1) (B)","C & P_L",1,0

<强>输出:

"c a|L G-3 (8) N (4th G P Q C- 4 R- 1 T H- 15.6 I- W 8.1) (B)|C & P_L",1,0

一些潜在的问题:它不处理|字符的转义,如果输入中有任何字符,没有错误处理等。为了更好的解决方案,您需要编写一个功能齐全的Perl脚本而不是单行。

答案 1 :(得分:0)

假设您的数据完全像它应该有效

$line =~ s-\",\"-|-g;