2016-01-31 39 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