awk - разбирать текст, имеющий тот же символ в полях, что и разделитель
Рассмотрим этот источник:
field1;field2;"data;data field3";field4;"data;data field5";field6
field1;"data;data field2";field3;field4;field5;"data;data field6"
Как вы можете видеть, разделитель полей используется внутри определенных полей, заключенных между "
, Я не могу напрямую разобраться с awk
потому что нет способа избежать нежелательного расщепления, по крайней мере, я не нашел способа. Кроме того, эти специальные поля имеют переменную позицию в строке и могут встречаться один, два, четыре раза и т. Д.
Я подумал о решении, включающем этап предварительного анализа, где я заменяю ;
в тех полях с кодом какой-то. Проблема в том, что sed
/ awk
выполнять жадный REGEX
матч. Так что в приведенном выше примере, я могу только заменить ;
в последнем поле, заключенном в кавычки в каждой строке.
Как я могу сопоставить каждый экземпляр цитаты и заменить конкретные ;
внутри них? Я не хочу использовать perl
или же python
и т.п.
2 ответа
С помощью gnu awk
Вы можете использовать специальные FPAT
переменная, чтобы иметь регулярное выражение для ваших полей.
Вы можете использовать эту команду, чтобы заменить все ;
от |
внутри двойных кавычек:
awk -v OFS=';' -v FPAT='"[^"]*"|[^;]*' '{for (i=1; i<=NF; i++) gsub(/;/, "|", $i)} 1' file
field1;field2;"data|data field3";field4;"data|data field5";field6
field1;"data|data field2";field3;field4;field5;"data|data field6"
В качестве альтернативы FPAT
Вы можете установить awk
FS
чтобы быть двойными кавычками, а затем поменяйте точку с запятой для каждого другого поля:
awk -F"\"" '{for(i=1;i<=NF;++i){ if(i%2==0) gsub(/;/, "|", $i)}} {print $0}' yourfile
Здесь awk есть:
- Расщепление записи по двойной кавычке (
-F"\""
) - Перебирая каждое найденное поле (
{for(i=1;i<=NF;++i)
) - Тестирование модуля порядкового номера поля 2, если он равен 0 (
if(i%2==0)
) - Если это даже тогда, то он меняет точки с запятой на трубы (
gsub(/;/, "|", $i)
) - Распечатывает преобразованную запись (
{print $0}
)