使用 awk /pattern/ { print "text"} /pattern/ {print ""} 时是否有 ELSE 模式?

Ali*_*Ali 22 awk

假设我有这样的文本文件:

R1 12 324 3453 36 457 4 7 8
R2 34 2342 2525 25 25 26 26 2 2
R3 23 2342 32 52 54 543 643 63
R4 25 234 2342 4 234242
Run Code Online (Sandbox Code Playgroud)

我想用awk不同的方式处理这些行,比如

awk '/R1/ { print "=>" $0} /R2/ { print "*" $0} '
Run Code Online (Sandbox Code Playgroud)

并且我还想按原样打印所有其余的行(不复制我已经处理过的行),基本上我需要 /ELSE/ { print $0}在行的末尾awk

有这样的事情吗?

jay*_*ngh 27

简化方法 awk

awk '/R1/ {print "=>" $0;next} /R2/{print "*" $0;next} 1' text.file

[jaypal:~/Temp] cat text.file 
R1 12 324 3453 36 457 4 7 8
R2 34 2342 2525 25 25 26 26 2 2
R3 23 2342 32 52 54 543 643 63
R4 25 234 2342 4 234242

[jaypal:~/Temp] awk '/R1/ { print "=>" $0;next} /R2/{print "*" $0;next}1' text.file
=>R1 12 324 3453 36 457 4 7 8
*R2 34 2342 2525 25 25 26 26 2 2
R3 23 2342 32 52 54 543 643 63
R4 25 234 2342 4 234242
[jaypal:~/Temp] 
Run Code Online (Sandbox Code Playgroud)

突破模式 {Action} 语句:

  • /R1/ { print "=>" $0;next}: 这意味着将完成具有/R1/打印动作的=>行。next意味着其余的 awk 语句将被忽略并查看下一行。

  • /R2/{print "*" $0;next}: 这意味着将完成pattern /R2/与打印动作相匹配的*行。当awk处理开始时,第一个pattern {action}语句将被忽略,因为pattern /R1/不会为有行的真/R2/。这样第二个pattern {action}语句就行了。next再次意味着我们不想要任何更多的处理,awk将适时转到下一行。

  • 1打印所有行。当只提供一个条件 no 时{action},awk 默认为 using {print}。这里的条件是1被解释为真,所以它总是成功。如果我们到了这一点,那是因为第一个和第二个pattern {action}语句被忽略或绕过(对于不包含/R1/and 的行/R2/),因此将对其余行执行默认打印操作。


Chr*_*own 7

awk在涉及条件时实现通常的嫌疑人。使用printf而不是print用于您想要在比赛中完成的工作是个好主意。

awk '{ if (/^R1/) { printf("=> %s\n", $0) } else if (/^R2/) { printf("* %s\n", $0) } else { print $0 } }'
Run Code Online (Sandbox Code Playgroud)

  • 我不明白在这里使用 `printf` 的意义。它唯一的优点(除非你做的格式比串联更漂亮)是它不添加换行符,这在这里不相关。 (2认同)

Ale*_*puy 5

Chris Down 已经展示了如何通过在块中使用显式“if”语句为正则表达式获取 else。您也可以通过其他方式获得相同的效果,尽管他的解决方案可能更好。

一种是编写第三个正则表达式,它只匹配与其他正则表达式不匹配的文本,在您的情况下,这看起来像这样:

awk '/^R1/ { print "=>" $0}
     /^R2/ { print "*" $0}
     /^[^R]/ || /^R[^12]/ { print $0 } '
Run Code Online (Sandbox Code Playgroud)

请注意,这使用了锚定的正则表达式 - 正则表达式开头的 ^ 只会在一行的开头匹配 - 您的原始模式没有这样做,这会稍微减慢匹配速度,因为它会检查一行上的所有字符而不是跳到下一行。第三个(“else”)情况将匹配以某个不是 'R' ([^R]) 的字符开头或以 'R' 开头后跟一个不是 '1' 或 ' 的字符的行2' (R[^12])。^ 两种不同的含义有点令人困惑,但这个错误是很久以前犯的,很快就不会改变。

要使用互补的正则表达式,它们确实需要被锚定,否则 [^R] 将匹配例如它后面的 1。对于像您这样非常简单的正则表达式,这种方法可能很有用,但是随着正则表达式变得更加复杂,这种方法将变得难以管理。相反,您可以为每一行使用状态变量,如下所示:

awk '{ handled = 0 }
     /^R1/ { print "=>" $0; handled = 1}
     /^R2/ { print "*" $0; handled = 1}
     { if (!handled) print $0 } '
Run Code Online (Sandbox Code Playgroud)

这将每个新行的处理设置为零,如果它匹配两个正则表达式中的任何一个,则设置为 1,最后,如果它仍然为零,则执行打印 $0。

  • `if (!handled)` 糟糕!使用 `next` 停止考虑其他操作。 (4认同)