Answers:
简化方法 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]
模式{Action}语句的突破:
/R1/ { print "=>" $0;next}
:这意味着将执行具有/R1/
打印作用的=>
行。next
表示其余的awk语句将被忽略,并查看下一行。
/R2/{print "*" $0;next}
:这意味着将完成pattern /R2/
与打印操作相符的*
行。当awk
处理开始时,第一条pattern {action}
语句将被忽略,因为pattern /R1/
对于具有的行,则将不是true /R2/
。因此,第二条pattern {action}
语句就可以了。next
再次表示我们不希望再进行任何处理,awk
将适当地转到下一行。
1
打印所有行。如果仅提供一个条件而没有{action}
,则awk默认使用{print}
。在此条件被1
解释为真,因此它总是成功。如果到了这一点,那是因为第一和第二条pattern {action}
语句被忽略或绕过(对于不包含/R1/
和的行/R2/
),因此将对其余行执行默认的打印操作。
awk
在涉及条件时实施通常的怀疑。最好使用printf
而不是print
要在比赛中完成的工作。
awk '{ if (/^R1/) { printf("=> %s\n", $0) } else if (/^R2/) { printf("* %s\n", $0) } else { print $0 } }'
if-then-else
这个。
next
是awk编程中的重要工具。
printf
这里使用的意义。它的唯一优点(除非您要进行比串联更高级的格式化)是它没有添加换行符,这在此不相关。
print
仅需输出,$0
而printf
必须解析格式字符串。
Chris Down已经展示了如何通过在块中使用显式的“ if”语句来获取正则表达式的else。您也可以通过其他方式获得相同的效果,尽管他的解决方案可能更好。
一种是编写第三个正则表达式,该正则表达式将仅匹配其他文本不匹配的文本,在您的情况下,看起来像这样:
awk '/^R1/ { print "=>" $0}
/^R2/ { print "*" $0}
/^[^R]/ || /^R[^12]/ { print $0 } '
请注意,这使用锚定的正则表达式-正则表达式开头的^仅在行的开头匹配-您的原始模式不这样做,这会稍微减慢匹配速度,因为它将检查行中的所有字符,而不是跳过直到下一行。第三种(“ 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 } '
对于每个新行,此设置将处理为零,如果它与两个正则表达式中的任何一个匹配,则将其设置为1,最后,如果仍为零,则执行打印$ 0。
if (!handled)
!使用next
停止考虑其他行动。
if (!handled)
。通用,灵活,可重用的解决方案是好的。如果下一个有此问题的人想要在打印后进行更多处理怎么办?答案next
不支持。