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

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

Читая ваши требования, вы описываетедваразные выражения длядве разные работы. Ты говоришь :

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

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

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

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

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

awk '/[*→]/{print a; a=$0}' file

решение2

С примечанием о печатипредыдущийлинии, когда видите звездочку, итекущийлиния при виде :

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

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

решение3

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

awk '/\*/ || /→/ {print}' /path/to/file

решение4

Это дает ожидаемые результаты, которые вы цитируете. Нет необходимости экранировать *, поскольку мы можем положиться на поведение "В 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

Связанный контент