我必须解析一个csv文件并将其内容转储到mysql表中。
# 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
对于第二个输出,它可以是我选择的任何标题集。 然后我可以使用load data infile将这个输出数据加载到mysql表中。寻找awk脚本来实现这一目标。需要帮助请叫我。 TX。
答案 0 :(得分: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
存储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 ""
语句来删除每个块之间的换行符。
答案 1 :(得分: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>
----
上面使用FPAT
的GNU awk,其他awks你需要while(match(...))
循环。
请参阅http://www.gnu.org/software/gawk/manual/gawk.html#Splitting-By-Content了解FPAT
如何将输入拆分为字段。除此之外:
sub()
并测试NF
丢弃评论和空行。gsub()
用换行符替换每次出现的\"
,这样转义引号就不会被字段拆分,而且这个操作对整个记录起作用的事实会导致awk之后重新分割,以便在该点再次应用FPAT
,确保原始\"
对进入循环的字段没有影响。gsub()
将恢复当前字段中最初存在的\"
gsub()
只修剪当前字段的所有前导和尾随空格。gsub()
会从字段中删除开始/结束引号。其余应该是显而易见的。我正在剥离使用f[]
而不是填充位置的前导/尾随空格和引号,因为您似乎想要至少2个不同的输出,一个带有周围的引号而另一个没有,但是您可以选择其中任何一个gsub()
已完成。
要学习awk - 请阅读Arnold Robbins撰写的第四版Effective Awk编程一书。