因为我同时写了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`
这有更好的方法吗?
答案 0 :(得分:1)
您通常应该避免使用正则表达式解析CSV,正如Kent Fredric在another 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;