awk: объедините выражения логическим ИЛИ

Я хочу объединить (логическое ИЛИ) два выражения awk. По отдельности оба работают нормально. Первое выражение выводит строку прямо перед поисковым запросом. Второе выражение просто печатает строку, содержащую специальный символ. Если я объединю оба выражения оператором ИЛИ, я получу ошибку «

^ неожиданный перевод строки или конец строки

»

awk '(({$0~/\*/; print a; a=$0}) || (/\→/))' file.txt

file.txt выглядит следующим образом:

foo
*
bla
bla
bar→
bar→
foo
*
bla
bla
bar→
foo
*
bla
bar→
bar→

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

foo
bar→
bar→
foo
bar→
foo
bar→
bar→
-1
13.04.2017, 00:05
4 ответа

С примечанием о печати предыдущей строки при отображении звездочки и текущей строки при отображении :

awk '/\*/ {print prev} /\→/ {print} {prev=$0}' file.txt

/ pattern / {action} - это сокращение от $ 0 ~ / pattern / {action} . Первое действие печатает переменную prev , если в строке есть звездочка, второе - печатает текущую строку, если есть стрелка, и, наконец, мы безоговорочно сохраняем текущую строку в prev , чтобы он был доступен для печати, если следующая строка совпадает.

1
28.01.2020, 05:07

Читая ваши требования, вы описываете два разных выражений для двух разных заданий . {{1} } Вы говорите:

First expression prints the line right before the search term
Second expression just prints the line that contains a special character

Это означает, что эти два выражения НЕ могут быть объединены в OR. Вы комбинируете с выражениями ИЛИ, которые будут выполнять одно и то же действие.

В результате правильный ответ, согласно вашей формулировке:

$ awk '/\*/{print a}{a=$0}/\→/' <<<"$a"
foo
bar→
bar→
foo
bar→
foo
bar→
bar→

Если вам действительно нужно использовать условие ИЛИ, чтобы выполнить одно и то же действие для двух разных условий, вы можете сделать это также следующим образом:

awk '/[*→]/{print a; a=$0}' file
2
28.01.2020, 05:07

Это должно работать:

awk '/\*/ || /→/ {print}' /path/to/file
1
28.01.2020, 05:07

Это дает ожидаемые результаты, которые вы цитируете. Нет необходимости избегать *, потому что мы можем полагаться на «В POSIX awk и gawk операторы« * »,« + »и«? »Означают сами себя, когда в регулярном выражении нет ничего, что им предшествует». поведение здесь, подробнее на https://www.gnu.org/software/gawk/manual/gawk.html#Regexp

$ awk '/*/||/→/' file.txt
foo*
bar→
bar→
foo**
bar→
foo*
bar→
bar→
$

Использование grep вместо:

$ grep -E '\*|→' file.txt
0
28.01.2020, 05:07

Теги

Похожие вопросы