RS на языке awk

Я изучаю язык программирования awk, и я застрял здесь проблема.

У меня есть файл (awk.dat), имеющий следующее содержимое:

Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Maecenas pellentesque erat vel tortor consectetur condimentum.
Nunc enim orci, euismod id nisi eget, interdum cursus ex.
Curabitur a dapibus tellus.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
Aliquam interdum mauris volutpat nisl placerat, et facilisis.

Я использую приведенную ниже команду:

awk 'BEGIN{RS="*, *";ORS="<<<---\n"} {print $0}' awk.dat

это возвращает мне ошибку:

awk: run time error: regular expression compile failed (missing operand)
*, *
    FILENAME="" FNR=0 NR=0

Пока, если я использую команду: awk 'BEGIN{RS=" *, *";ORS="<<<---\n"} {print $0}' awk.datДает требуемый результат.

Мне нужно понять эту часть: RS=" *, *", смысл пространства между двойными кавычками и * до ,, из-за чего выкидывает ошибку.

Ожидаемый результат:

Lorem ipsum dolor sit amet<<<---
consectetur adipiscing elit.
Maecenas pellentesque erat vel tortor consectetur condimentum.
Nunc enim orci<<<---
euismod id nisi eget<<<---
interdum cursus ex.
Curabitur a dapibus tellus.
Lorem ipsum dolor sit amet<<<---
consectetur adipiscing elit.
Aliquam interdum mauris volutpat nisl placerat<<<---
et facilisis.
<<<---

Благодарю.

3 ответа

Решение
"[space1]*,[space2]*"

является регулярным выражением, оно соответствует строке с:

ноль или много пробелов (space1), за которыми следует запятая, затем следует ноль или много пробелов (space2)

Первый "*,[space]*" был неправ, потому что * имеет особое значение в регулярных выражениях. Это означает, что повторяющаяся совпадающая группа / символ ноль или много раз. Вы не можете поставить это в самом начале.

Имейте в виду, что, согласно POSIX, RS определяется как один символ, а не как регулярное выражение.

Первый символ строкового значения RS должен быть разделителем входных записей; по умолчанию. Если RS содержит более одного символа, результаты не указаны. Если RS равно нулю, то записи разделяются последовательностями, состоящими из плюс одна или несколько пустых строк, начальные или конечные пустые строки не должны приводить к пустым записям в начале или конце ввода, а всегда должен быть разделитель полей, независимо от значения FS является.

Источник: Awk Posix стандарт

Это подразумевает, что RS=" *, *" приводит к неопределенному поведению.

Другие версии awk, которые реализуют расширения для POSIX, могут иметь другой подход к RS обозначает. Примерами являются GNU awk и mawk. Оба реализуют RS быть регулярным выражением, но обе реализации немного отличаются. Сводка по использованию <звездочки>:

| RS   | awk (posix)  | gawk             | mawk             |
|------+--------------+------------------+------------------|
| "*"  | "<asterisk>" | "<asterisk>"     | "<asterisk>"     |
| "*c" | undefined    | "<asterisk>c"    | undefined        |
| "c*" | undefined    | "","c","ccc",... | "","c","ccc",... |

c is any character

Вышесказанное должно объяснить ошибку ОП как RS="*, *" недопустимое регулярное выражение в соответствии с mawk.

$ echo "abc" | ./mawk '/*c/'
mawk: line 1: regular expression compile failed (missing operand)

GNU awk: Руководство по GNU awk гласит следующее:

Когда используешь gawk, стоимость RS не ограничивается односимвольной строкой. Это может быть любое регулярное выражение (см. Regexp). (ce) Как правило, каждая запись заканчивается следующей строкой, соответствующей регулярному выражению; следующая запись начинается в конце соответствующей строки.

источник: руководство по GNU awk

Чтобы понять использование в регулярном выражении в GNU awk, мы находим:

<звездочка> * Этот символ означает, что предыдущее регулярное выражение должно повторяться столько раз, сколько необходимо, чтобы найти совпадение. Например, ph* применяет * символ предыдущего h и ищет совпадения одного p с последующим любым количеством h s. Это также соответствует просто p если нет h с присутствуют.

Есть два тонких момента, чтобы понять, как * работает. Во-первых, * применяется только к одному предшествующему компоненту регулярного выражения (например, в ph* это относится только к h). Вызывать * чтобы применить к большему подвыражению, используйте круглые скобки: (ph)* Матчи ph, phph, phphph, и так далее.

Во-вторых, * находит как можно больше повторений. Если текст для сопоставления phhhhhhhhhhhhhhooey, ph* соответствует всем h s.

источник: GNU Операторы регулярных выражений

Следует отметить, однако, что:

В POSIX awk и gawk, * , + а также ? операторы отстаивают себя, когда в регулярном выражении нет ничего, что предшествует им. Например, /+/ соответствует буквальному плюсу. Однако многие другие версии awk рассматривают такое использование как синтаксическую ошибку.

источник: GNU Операторы регулярных выражений

Таким образом, установка RS="*, *", подразумевает, что это будет соответствовать строкам "*,", "*, ", "*, "...

$ echo "a,b, c" | awk 'BEGIN{RS="*, *"}1'
a,b, c
$ echo "a*,b, c" | awk 'BEGIN{RS="*, *"}1'
a
b, c

mawk: Руководство по GNU awk гласит следующее:

12. Многострочные записи
поскольку mawk толкует RS как регулярное выражение, многострочные записи просты.

источник: man mawk

но

11. Разделение строк, записей и файлов
Программы Awk используют один и тот же алгоритм для разбиения строк на массивы с split() и записи в поля на FS, mawk использует практически тот же алгоритм для разделения файлов на записи RS ,

Split(expr,A,sep) работает следующим образом:

  1. <Вырезано>
  2. Если sep = " " (один пробел), затем обрезается спереди и сзади expr, а также sep становится <ПРОБЕЛ>. mawk определяет как регулярное выражение /[ \t\n]+/, Иначе sep обрабатывается как регулярное выражение, за исключением того, что метасимволы игнорируются для строки длиной 1, например, split(x, A, "*") а также split(x, A, /\*/) подобные.
  3. <Вырезано>

источник: man mawk

В руководстве не упоминается, как следует интерпретировать регулярное выражение, начинающееся с метасимвола (например, "*c")


Примечание: в разделе GNU awk я описал POSIX awk, поскольку, согласно POSIX, регулярное выражение вида "*, " приводит к неопределенному поведению. (Это не зависит от определения RS как RS в любом случае не ERE в POSIX awk)

Утилита awk должна использовать расширенную запись регулярного выражения (см. Расширенные регулярные выражения XBD)

Источник: Awk Posix стандарт

а также

*+?{ <Звездочка>, <знак плюс>, <знак вопроса> и <левая скобка> должны быть специальными, за исключением случаев, когда они используются в выражении в скобках (см. RE выражение в скобках). Любое из следующих применений приводит к неопределенным результатам:

  • Если эти символы появляются первыми в ERE или сразу после неэкранированных <вертикальная линия>, <окружность>, <знак доллара> или <левая скобка>
  • Если <левая скобка> не является частью правильного выражения интервала (см. ERE, соответствующие нескольким символам)

источник: расширенные регулярные выражения POSIX

Не могли бы вы попробовать следующий раз.

awk '{gsub(", ","<<<---" ORS)} 1;END{print "<<<---"}'   Input_file
Другие вопросы по тегам