2016-01-31 67 views
2

我必須解析一個csv文件並將其內容轉儲到mysql表中。使用awk將csv文件解析爲數組

 

# myfile.csv 

# Contents 
# Sample Headers 

"header1 with quotes", header2withoutquotes, "header3", header4, hdeader5 
"Sample Text",2,3,4,"MoreText, with commas" 
"Text2 with escaped \"",8,6,7,9 
"Text3",876,0.6,7,10 

首頁輸出

 

rowid|header1 with quotes|Sample Text|myfile 
1|header2withoutquotes|2|myfile 
1|header3|3|myfile 
1|header4|4|myfile 
1|header5|MoreText, with commas|myfile 

2|header1 with quotes|Text2 with escaped \"|myfile 
2|header2withoutquotes|8|myfile 
2|header3|6|myfile 
2|header4|7|myfile 
2|header5|9|myfile 

3|header1 with quotes|text3|myfile 
3|header2withoutquotes|876|myfile 
3|header3|0.6|myfile 
3|header4|7|myfile 
3|header5|10|myfile 

在輸出的第二我需要自定義頁眉進行水平對齊。例如

 

rowid|"header1 with quotes"|"header3"|header4|filename 
1|Sample Text|3,4,myfile 
2|Text2 with escaped \"|6|7|myfile 
3|Text3|0.6|7|myfile 

對於第二個輸出,它可以是我選擇的任何一組標題。 然後,我可以使用加載數據infile將此輸出數據加載到mysql表中。尋找awk腳本來實現這一點。需要幫助請叫我。 TX。

+0

請原諒未格式化的數據。仍在學習...... – user676500

+0

@edmorton按照要求編輯了問題。 – user676500

+0

如果您需要使用嵌入逗號和引號來處理CSV的完整複雜性,那麼您可能最好使用Python或Perl以及可用的CSV模塊,或者使用專門的工具,如CSVfix(該工具位於Google Code上有一次,但現在已經閉店了;我不確定這些日子的官方消息來源,這很令人尷尬)。 –

回答

0

我會離開的輸出格式給你,但這裏是如何處理嵌入的逗號之後創建字段的數組和轉義引號和不良場所周邊的一些領域,所以你就可以做任何你想要與他們:

$ cat tst.awk 
BEGIN { FPAT = "([^,]*)|(\"[^\"]+\")" } 
{ sub(/#.*/,"") } 
NF { 
    # replace all escaped quotes with a newline and resplit the record 
    gsub(/\\"/,RS) 

    for (i=1;i<=NF;i++) { 
     # restore the escaped quotes in this field 
     gsub(RS,"\\\"",$i) 

     f[i] = $i 
    } 

    for (i=1;i<=NF;i++) { 
     # remove this to leave leading/trailing white space: 
     gsub(/^[[:space:]]+|[[:space:]]+$/,"",f[i]) 

     # remove this to leave quotes around fields: 
     gsub(/^"|"$/,"",f[i]) 

     print NR, NF, i, "<" f[i] ">" 
    } 
    print "----" 
} 

$ awk -f tst.awk file 
4 5 1 <header1 with quotes> 
4 5 2 <header2withoutquotes> 
4 5 3 <header3> 
4 5 4 <header4> 
4 5 5 <hdeader5> 
---- 
5 5 1 <Sample Text> 
5 5 2 <2> 
5 5 3 <3> 
5 5 4 <4> 
5 5 5 <MoreText, with commas> 
---- 
6 5 1 <Text2 with escaped \"> 
6 5 2 <8> 
6 5 3 <6> 
6 5 4 <7> 
6 5 5 <9> 
---- 
7 5 1 <Text3> 
7 5 2 <876> 
7 5 3 <0.6> 
7 5 4 <7> 
7 5 5 <10> 
---- 

以上使用GNU AWK爲FPAT,與其他awks你需要一個while(match(...))循環。

請參閱http://www.gnu.org/software/gawk/manual/gawk.html#Splitting-By-Content瞭解FPAT如何將輸入拆分爲字段。除此之外:

  1. 第一個sub()並測試NF放棄註釋和空行。
  2. gsub()在循環之前用換行符替換\"的每一個出現處,以便逃逸的引號不會妨礙字段拆分,並且此操作在整個記錄上工作的事實導致awk之後重新拆分,所以FPAT在該點再次應用,確保原始的\"對進入循環的字段沒有影響。
  3. 在第一環的gsub()恢復任何\" s表示原本存在於當前場
  4. 在第二循環中的第一個gsub()剛剛修剪所有前導和尾部的空白斷電流場。
  5. 第二個循環中的第二[可選] gsub()刪除字段中的開始/結束引號。

其餘的應該是顯而易見的。我正在使用f[]而不是其填充位置的前導/尾隨空格和引號,因爲您似乎至少需要2個不同的輸出,其中一個使用了周圍的引號,另一個沒有使用,但是您的選擇是在那些gsub() s中完成。

學習awk - 獲得Arnold Robbins編寫的Effective Awk編程第4版。

+1

Tx @edmorton。感謝你的努力。 – user676500

1

這應該工作:

{ 
    if(NR==1) 
     split($0,header,",") 
    else 
    { 
     split($0,line,",") 
     for (i in line) 
     { 
      gsub(/^[ \t]+|"|[ \t]+$)/, "", header[i]); 
      gsub(/^[ \t]+|"|[ \t]+$)/, "", line[i]); 
      print header[i]"|"line[i]"|"FILENAME 
     } 
     print "" 
    } 
} 

基本上它存儲header陣列中的第一行中,然後將其split S上的elem陣列中的每個線和飾件遠離前緣和後空格或製表符。最後,它組成輸出字符串。

輸出:

header1|text1|file2 
header2|2|file2 
header3|3|file2 
header4|4|file2 
hdeader5|moretext|file2 

header1|text2|file2 
header2|8|file2 
header3|6|file2 
header4|7|file2 
hdeader5|9|file2 

header1|text3|file2 
header2|876|file2 
header3|0.6|file2 
header4|7|file2 
hdeader5|10|file2 

您可以通過刪除最後print ""聲明擺脫各塊之間的換行。

+0

Tx @Cynical。我忘了提及文本之間存在的逗號。例如說:「有些,更多的文字,中間有逗號」。這些將是一個問題嗎?剛剛在我的csv文件上運行這個腳本,並意識到我的錯誤。有什麼建議麼? – user676500

+0

示例:「某些文本」,文本,「某些文本,帶逗號」,「標準文本引號」。再次發送。 – user676500

+0

是的,這可能是一個問題......是否有可能文本與逗號總是**引號括起來? – Cynical