2015-02-24 46 views
1

因为此时我写了一个对question, what got closed的回答 - 试图对其进行改写和重新提问。使用正则表达式更改CSV文件

经与180个milions记录的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 

例如需要拼接的colums 1,2,3与|并打印为一列并保持不变,其他colums

用正则表达式试了一下:

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` 

这里是什么更好的办法?

+1

不要重复提问。编辑您的上一个问题。 – 2015-02-24 17:09:28

回答

1

通常你应该避免与正则表达式解析的CSV,如Kent Fredric解释在回答another similar question

不使用CPAN真是一个灾难。

在尝试编写自己的CSV实现之前,请考虑这一点。 Text :: CSV包含超过一百行代码,包括修正的缺陷和边缘案例, 并且从头开始重新编写这些代码只会让您了解CSV如何成为困难的方式。

这是真的不好的做法,试图解析与正则表达式的CSV,因为例如,你需要处理:

  • 转义引号
  • 转义分隔符包含定界符
  • 领域

等等,所有的Text :: CSV都会处理y OU。

下面是使用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脚本,而不是一行代码。

+0

您可能会感到惊讶,但正则表达式并非总是适合这项工作的正确工具,CSV解析与普遍的观点相反*而非微不足道。所以有选择,要么重新发明自己的(破碎的)车轮,要么使用正确的工具来完成这项工作。 – 2015-02-24 15:28:42

+1

我知道你试图直接回应已经关闭的问题的OP,但是“对话框”(例如“另一方面,我理解你,你可能不是程序员)”。这里真的没什么意义。我已经清理过了,所以你的回答对其他用户来说实际上是有意义的。我认为你应该编辑原件,而不是过于宽泛,如果他们认为该问题对该网站有价值,则可以投票重新开放。 – ThisSuitIsBlackNot 2015-02-24 15:43:15

+1

@ThisSuitIsBlackNot没错。我明白 - 你是对的 - 感谢你的编辑。 (对不起,我只是因为一些评论而感到有些沮丧,需要冷静下来)。编辑原始问题并投票重新开放肯定是最好的方法。 – kobame 2015-02-24 16:15:15

0

假设你的数据是完全一样的是什么这应该工作

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