Выход из разделителя в двойных кавычках, в awk
Я использую awk для анализа моих данных с помощью "," как разделителя, так как вход представляет собой файл csv. Однако в данных, которые избегаются двойными кавычками ( "..." ), есть "," .
Пример
filed1,filed2,field3,"field4,FOO,BAR",field5
Как я могу игнорировать запятую "," внутри двойной кавычки, чтобы я мог правильно разобрать вывод с помощью awk? Я знаю, что мы можем сделать это в Excel, но как это сделать в awk?
Ответы
Ответ 1
Для очень подробного описания смотрите здесь:
http://backreference.org/2010/04/17/csv-parsing-with-awk/ (версия archive.org)
Но это не синтаксический анализ, а обман с регулярным выражением. Для чего-либо более сложного, чем примеры на странице, вы должны использовать Perl/Python с библиотекой синтаксического анализатора, например, "csv" для Python.
Ответ 2
Это просто, с GNU awk 4:
zsh-4.3.12[t]% awk '{
for (i = 0; ++i <= NF;)
printf "field %d => %s\n", i, $i
}' FPAT='([^,]+)|("[^"]+")' infile
field 1 => filed1
field 2 => filed2
field 3 => field3
field 4 => "field4,FOO,BAR"
field 5 => field5
Добавление некоторых комментариев согласно требованию OP.
Из руководства по GNU awk "Определение полей по содержанию":
Значение FPAT должно быть строкой, предоставляющей регулярное выражение. Это регулярное выражение описывает содержимое каждого поля. В случае данных CSV, представленных выше, каждое поле представляет собой либо "все, что не является запятой", либо "двойную кавычку, все, что не является двойной кавычкой и закрывающей двойной кавычкой". Если бы записать как константу регулярного выражения, мы бы имели /([^,]+)|("[^"]+")/
. Запись этого в виде строки требует от нас избежать двойных кавычек, приводящих к:
FPAT = "([^,]+)|(\"[^\"]+\")"
Использование +
дважды, это не работает должным образом для пустых полей, но это также можно исправить:
Как написано, регулярное выражение, используемое для FPAT, требует, чтобы каждое поле содержало хотя бы один символ. Простая модификация (изменение первого ' +
на' *
) позволяет пустым полям:
FPAT = "([^,]*)|(\"[^\"]+\")"
Ответ 3
FPAT работает, когда в цитированных полях есть символы новой строки и запятые, но не когда есть двойные кавычки, например:
field1,"field,2","but this field has ""escaped"" quotes"
Вы можете использовать простую программу-оболочку, которую я написал, называемую csvquote, чтобы упростить чтение данных awk, а затем восстановить проблемные специальные символы, например:
csvquote inputfile.csv | awk -F, '{print $4}' | csvquote -u
См. https://github.com/dbro/csvquote для кода и документов
Ответ 4
Полноценные синтаксические анализаторы CSV, такие как Perl Text::CSV_XS
, предназначены для обработки такого рода странности.
Предположим, вы хотите только напечатать 4-е поле:
perl -MText::CSV_XS -lne 'BEGIN{$csv=Text::CSV_XS->new()} if($csv->parse($_)){ @f=$csv->fields(); print "\"$f[3]\"" }' file
Входная строка разделяется на массив @f
Поле 4 является $f[3]
, поскольку Perl начинает индексирование при 0
В моем ответе я дал больше объяснений Text::CSV_XS
: проанализировать файл csv с помощью gawk