2009-09-18 92 views
3

我正在尝试编写一个awk脚本来将CSV格式的电子表格转换为XML格式的Bugzilla错误。输入CSV的格式如下(从XLS电子表格创建并保存为CSV):如何用awk解析逗号分隔值(csv)?

tag_1,tag_2,...,tag_N 
value1_1,value1_2,...,value1_N 
value2_1,value2_2,...,value2_N 
valueM_1,valueM_2,...,valueM_N 

头列表示XML标记的名称。转换成XML应该如上面的文件如下:

<element> 
    <tag_1>value1_1</tag_1> 
    <tag_2>value1_2</tag_2> 
    ... 
    <tag_N>value1_N</tag_N> 
</element> 
<element> 
    <tag_1>value2_1</tag_1> 
    <tag_2>value2_2</tag_2> 
    ... 
    <tag_N>value2_N</tag_N> 
</element> 
... 

的awk脚本我有做到这一点如下:

BEGIN {OFS = "\n"} 
NR == 1 {for (i = 1; i <=NF; i++) 
      tag[i]=$i 
     print "<bugzilla version=\"3.4.1\" urlbase=\"http://mozilla.com/\" maintainer=\"[email protected]\" exporter=\"[email protected]\">"} 
NR != 1 {print " <bug>" 
     for (i = 1; i <= NF; i++) 
      print "  <" tag[i] ">" $i "</" tag[i] ">" 
     print " </bug>"} 
END {print "</bugzilla>"} 

实际的CSV文件是:

cf_foo,cf_bar,short_desc,cf_zebra,cf_pizza,cf_dumpling ,assigned_to,bug_status,cf_word,cf_caslte 
ABCD,A-BAR-0032,A NICE DESCRIPTION - help me,pretty,Pepperoni,,,NEW,, 

实际输出是:

$ awk -f csvtobugs.awk bugs.csv

<bugzilla version="3.4.1" urlbase="http://mozilla.com/" maintainer="[email protected]" exporter="[email protected]"> 
    <bug> 
     <cf_foo,cf_bar,short_desc,cf_zebra,cf_pizza,cf_dumpling>ABCD,A-BAR-0032,A</cf_foo,cf_bar,short_desc,cf_zebra,cf_pizza,cf_dumpling> 
     <,assigned_to,bug_status,cf_word,cf_caslte>NICE</,assigned_to,bug_status,cf_word,cf_caslte> 
     <>DESCRIPTION</> 
     <>-</> 
     <>help</> 
     <>me,pretty,Pepperoni,,,NEW,,</> 
    </bug> 
    <bug> 
    </bug> 
</bugzilla> 

显然,不是预期的结果(我承认,我从这个论坛复制粘贴了这个脚本:http://www.unix.com/shell-programming-scripting/21404-csv-xml.html)。问题在于,从查看awk脚本开始已经过了很长时间,而且我没有IDEA语法的含义。

回答

4

您需要在BEGIN规则中设置FS = ","以将逗号用作字段分隔符;如果字段分隔符是一个选项卡,这是一种不同的(也是受欢迎的)惯例,即使不使用逗号也常常被称为“CSV”的文件中,但您显示它的代码应该可以正常工作;-)。

+0

击败我两个,所以我会接受你的! – les2 2009-09-18 17:02:54

+0

你也可以使用'-F'作为'awk' – 2009-10-31 17:36:03

0

我能够通过改变FS(字段分隔符)来解决它:

BEGIN { 
    FS=","; 
    OFS = "\n"} 
NR == 1 {for (i = 1; i <=NF; i++) 
      tag[i]=$i 
     print "<bugzilla version=\"3.4.1\" urlbase=\"http://mozilla.com/\" maintainer=\"[email protected]\" exporter=\"[email protected]\">"} 
NR != 1 {print " <bug>" 
     for (i = 1; i <= NF; i++) 
      print "  <" tag[i] ">" $i "</" tag[i] ">" 
     print " </bug>"} 
END {print "</bugzilla>"} 

输出:

<bugzilla version="3.4.1" urlbase="http://mozilla.com/" maintainer="[email protected]" exporter="[email protected]"> 
    <bug> 
     <cf_foo>ABCD</cf_foo> 
     <cf_bar>A-BAR-0032</cf_bar> 
     <short_desc>A NICE DESCRIPTION - help me</short_desc> 
     <cf_zebra>pretty</cf_zebra> 
     <cf_pizza>Pepperoni</cf_pizza> 
     <cf_dumpling ></cf_dumpling > 
     <assigned_to></assigned_to> 
     <bug_status>NEW</bug_status> 
     <cf_word></cf_word> 
     <cf_caslte></cf_caslte> 
    </bug> 
</bugzilla> 
1

使用的工具,你知道:)

这样awk脚本看起来没有处理“和其他CSV奇怪(我认为它只是分离在选项卡 - 其他答案注意它需要改变分裂,)python,perl .net等有对象来完全处理CSV一个nd XML,可能你可以用awk脚本中的字符数来编写解决方案,更重要的是可以理解它。

+0

的选项,嘿,它不需要很长时间,是吗?我已经想出了自己的答案,但只能在第一个答案后2秒(我的答案可以说更好,因为我包含更多信息):) – les2 2009-09-18 17:22:19

1

请记住,在一个CSV是分裂逗号是罚款,直到你得到以下情形:

1997,Ford,E350,"Super, luxurious truck" 

在这种情况下,它会分裂“超级豪华车”为两个项目不正确。我建议在上面的帖子中使用另一种语言的csv库作为'标记'状态。

+0

我通过切换到“TSV”导出来解决此问题(选项卡 - 分离值)。主文件是一个Excel工作表,我不需要一直这样做。 我正在将基于Excel的跟踪器(用于'敏捷'方法中'故事')的团队迁移到Bugzilla。现在每个故事都保存在Bugzilla中。我们使用Eclipse Mylyn插件将故事拉入IDE中作为任务。 IMO比Excel解决方案好得多。 无论如何,这个初始导入只需要发生一次 - 我不想为此学习Perl。 AWK脚本工作得很好:) – les2 2009-10-06 15:33:09

0

您可以试试我的csvprintf。它可以将CSV转换为XML,然后根据需要使用XSLT进行样式设置。