Text-Processing

使用 unix 命令從 csv 文件中提取第 4 列

  • March 3, 2017

我有一個格式如下的 csv 文件。

"col1","col2","col3","col4"
"1","text1","<p>big
     html
    text</p>
","4th column"
"2","text2","<p>big2
     html2
    text2</p>
","4th column2"

我想使用提取第四列。我認為這awk是最好的工具(如果我錯了,請告訴我)。我試過這個

awk -F, '{print $4}' myFile.csv 

但它失敗了。我認為因為第 3 列是多行之一。如何使用awk或任何其他 unix 命令來提取第 4 列。我正在尋找一個有效的解決方案,因為我的真實文件很大(> 2GB)

更新:

實際上,更簡單的方法是將記錄分隔符設置為gawk

$ gawk 'BEGIN{RS="\"\n"; FS=","}{print $4}' myFile.csv
"col4
"4th column
"4th column2

但是,這將刪除"每列末尾的尾隨。要解決這個問題,您可以自己列印:

$ gawk 'BEGIN{RS="\"\n"; FS=","}{print $4"\""}' myFile.csv
"col4"
"4th column"
"4th column2"

如果您根本不需要引號,可以將欄位分隔符設置為","

$ gawk 'BEGIN{RS="\"\n"; FS="\",\""}{print $3}' myFile.csv
col3
4th column
4th column2

我能想到的唯一方法這樣做的一種方法是首先修改文件然後解析它。在您的範例中,實際分隔兩條記錄的換行符始終遵循 a "

"col1","col2","col3","col4"   <-- here 
1,"text1","<p>big             <-- no "

如果整個文件都是這種情況,您可以將所有不在 a 之後的換行符替換"為佔位符,從而將所有內容都放在一行中。然後,您可以正常解析gawk並最終再次用換行符替換佔位符。我將使用該字元串&%&作為佔位符,因為它不太可能存在於您的文件中:

$ perl -pe 's/"\s*\n/"&%&/; s/\n//g; s/&%&/\n/;' myFile.csv | awk -F, '{print $4}'
"col4"
"4th column"
"4th column2"

-p標誌perl表示應用由 給出的print each line of the input file腳本後-e。然後有 3 個替換 ( s/foo/bar/) 命令:

  • s/"\s*\n/"&%&/: 這將找到"後面跟 0 個或多個空白字元 ( \s*) 和換行符 ( \n) 的任何字元。它將替換為"&%&. 添加引號以保留格式,並且&%&只是一個隨機佔位符,它可以是任何未出現在文件中的內容。
  • s/\n//g;:由於真正的換行符已被佔位符替換,我們現在可以安全地刪除此記錄中所有剩餘的換行符。這意味著目前記錄的所有行現在都已連接到目前行。
  • s/&%&/\n/:這會將佔位符轉換回正常的新行。

要了解命令的輸出,請在不執行以下命令的情況下執行它gawk

$ perl -pe 's/"\s*\n/"&%&/; s/\n//g; s/&%&/\n/;' myFile.csv 
"col1","col2","col3","col4"
1,"text1","<p>big      html     text</p>","4th column"
2,"text2","<p>big2      html2     text2</p>","4th column2"

所以,你現在有單行的長記錄,這是完美的食物gawk

您也可以直接在 Perl 中執行此操作:

perl -ne '$/="\"\n"; chomp;@a=split(/,/);print "$a[3]\"\n"' myFile.csv
"col4"
"4th column"
"4th column2"

這使用了更多的 Perl 魔法。$/特殊變數是輸入記錄分隔符。通過將其設置為,"\n我們告訴 Perl 拆分行不是 at,\n而是僅 at "\n",這樣每條記錄都將被視為單行。完成後,chomp從行尾刪除換行符(以便稍後列印)並split拆分每個記錄(on ,)並將其保存在 array 中@a。最後,我們列印數組的第 4 個元素(數組從 0 開始編號,因此是$a[3]),即第 4 列。

更神奇的是,打開自動吐痰 ( -a) 並用逗號 ( ) 分割F","。這會將每條記錄拆分為特殊@F數組,您可以列印數組的第 4 個元素:

$ perl -F"," -ane '$/="\"\n";chomp;print "$F[3]"' myFile.csv
"col4"
"4th column"
"4th column2"

引用自:https://unix.stackexchange.com/questions/106047