2015-02-24 54 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;