как вы анализируете запятые-значения (CSV) с awk? - PullRequest
3 голосов
/ 18 сентября 2009

Я пытаюсь написать сценарий awk для преобразования электронной таблицы в формате CSV в XML для ошибок Bugzilla. Формат входного CSV выглядит следующим образом (создан из электронной таблицы XLS и сохранен как 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=\"somebody@mozilla.com\" exporter=\"somebody.else@mozilla.com\">"}
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="somebody@mozilla.com" exporter="somebody.else@mozilla.com">
   <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). Проблема в том, что он SOOOOO давно, так как я смотрел на скрипты awk и у меня НЕТ ИДЕИ что означает синтаксис.

Ответы [ 6 ]

4 голосов
/ 18 сентября 2009

Вам необходимо установить FS = "," в правиле BEGIN, чтобы использовать запятую в качестве разделителя полей; код, который вы показываете, должен работать, если разделитель полей был табуляцией, что является другим (также популярным) соглашением в файлах, которые часто все еще называют «CSV», даже если запятые не используются; -).

1 голос
/ 04 октября 2009

Помните, что разделение через запятую в csv - это нормально, пока вы не получите следующий сценарий:

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

В этом случае «Супер, роскошный грузовик» разделится на две части, что неверно. Я бы порекомендовал использовать библиотеки csv на другом языке в качестве отметки 'Mark' в приведенном выше сообщении.

1 голос
/ 18 сентября 2009

Используйте инструмент, который вы знаете:)

Этот awk-скрипт не выглядит так, как он имеет дело с "и другими странностями CSV. (Я думаю, что он просто разбивается на вкладки - как и другие ответы отмечают, что его нужно изменить, чтобы разделить на) Python, Perl .Net и т.д. имеют объекты чтобы в полной мере иметь дело с CSV и XML, и, возможно, вы могли бы написать решение в несколько символов, как в сценарии awk, и БОЛЬШЕ его понимают.

0 голосов
/ 20 июля 2011

Вместо этого вы можете попробовать мой csvprintf . Он может конвертировать CSV в XML, который затем можно при желании оформить с помощью XSLT.

0 голосов
/ 26 сентября 2009

Вы можете использовать различные приемы, такие как настройка FS. Больше трюков можно найти в новостной группе Awk. Есть также парсеры типа моего: http://lorance.freeshell.org/csv/

0 голосов
/ 18 сентября 2009

Мне удалось это исправить, изменив 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=\"somebody@mozilla.com\" exporter=\"somebody.else@mozilla.com\">"}
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="somebody@mozilla.com" exporter="somebody.else@mozilla.com">
   <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>
...