Я хочу объединить (логическое ИЛИ) два выражения 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