RS на языке awk - PullRequest
       81

RS на языке awk

0 голосов
/ 04 декабря 2018

Я изучаю язык программирования 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 ]

0 голосов
/ 04 декабря 2018

Имейте в виду, что, согласно 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

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

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

GNU awk: В руководстве по GNU awk говорится следующее:

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

source: GNU awk manual

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

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

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

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

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

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

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

source: 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. Если sep = " " (один пробел), то обрезается спереди и сзади от expr, а sep становится .mawk определяет как регулярное выражение /[ \t\n]+/.В противном случае sep рассматривается как регулярное выражение, , за исключением того, что метасимволы игнорируются для строки длиной 1 , например, split(x, A, "*") и split(x, A, /\*/) одинаковы.

источник: man mawk

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


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

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

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

и

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

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

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

0 голосов
/ 04 декабря 2018

Не могли бы вы попробовать один раз.

awk '{gsub(", ","<<<---" ORS)} 1;END{print "<<<---"}'   Input_file
0 голосов
/ 04 декабря 2018
"[space1]*,[space2]*"

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

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

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

...