awk:通过逻辑或组合表达式

awk:通过逻辑或组合表达式

我想要组合(逻辑或)两个 awk 表达式。两者分开工作都很好。第一个表达式打印搜索词之前的行。第二个表达式仅打印包含特殊字符的行。如果我通过 OR 运算符组合 bothe 表达式,我会收到错误'

^ 意外的换行符或字符串结尾

'

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

这意味着这两个表达式不能以 OR 形式组合。您可以与 OR 表达式组合来执行相同的操作。

因此,根据您的措辞,正确答案是:

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

如果您确实需要使用 OR 条件以便对两个不同的条件执行相同的操作,您也可以这样做:

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

相关内容