Я хочу объединить (логическое ИЛИ) два выражения 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→
С примечанием о печати предыдущей строки при отображении звездочки и текущей строки при отображении →
:
awk '/\*/ {print prev} /\→/ {print} {prev=$0}' file.txt
/ pattern / {action}
- это сокращение от $ 0 ~ / pattern / {action}
. Первое действие печатает переменную prev
, если в строке есть звездочка, второе - печатает текущую строку, если есть стрелка, и, наконец, мы безоговорочно сохраняем текущую строку в prev
, чтобы он был доступен для печати, если следующая строка совпадает.
Читая ваши требования, вы описываете два разных выражений для двух разных заданий . {{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
Это дает ожидаемые результаты, которые вы цитируете. Нет необходимости избегать *, потому что мы можем полагаться на «В 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