有没有办法停止处理 awk 中的单行?是否有类似break
或continue
的东西适用于模式动作对而不是动作中的控制结构?
假设我有以下input.txt
文件,并且我尝试将每个名称替换为x0
, x1
, x2
, ...
。但是,我想留下以空格或-
单独开头的行。
-- data
bob 4
joe 5
bob 6
joe 7
变成:
-- data
x0 4
x1 5
x0 6
x1 7
我有以下脚本可以做到这一点。 (顺便说一句,可能有一种更好的方法来使用定界符而不是大量的字符串文字来构造它)。
#!/bin/sh
awk '
BEGIN { c = 0; }
# do not process lines beginning with - or space
/^[- ]/ {
print;
}
# update
/^[^- ]/ {
if (! ($1 in name) ) {
new_name = "x" c;
c += 1;
name[$1] = new_name;
}
$1 = name[$1];
print;
}
' input.txt
这个脚本还有一些不足之处。首先,我们知道/^[- ]/
和/^[^- ]/
是相互排斥的,但该属性并没有在任何地方强制执行。我希望能够使用类似break
在第一场比赛后放弃处理该行的方法。
/^[- ]/ {
print;
break;
}
我希望能够添加另一个子句,以在存在与前两个模式都不匹配的非空行时提醒用户出现问题。
/./ {
print "non-empty line!" > "/dev/stderr"
# or print "non-empty line!" > "/dev/tty" if portability is a concern
}
但是,如果我按原样将此模式操作对添加到脚本中,它将在每个非空行后触发。
在前两个测试用例之后我可以添加一些东西来停止处理该行,因为它已经“成功”处理了?如果这是不可能的,是否有一个通用的 awk 习惯用法来处理包罗万象的情况?
答案1
您可以使用该awk
语句next
立即继续处理下一个输入记录。
这是脚本的替代实现awk
:
awk '/^[- ]/ { print; next } !($1 in n) { n[$1] = sprintf("x%d", c++) } { $1 = n[$1]; print }' data.in
代码awk
是
/^[- ]/ { print; next }
!($1 in n) { n[$1] = sprintf("x%d", c++) }
{ $1 = n[$1]; print }
c
是柜台。从一开始它就为零。
n
是保存新标签/名称的关联数组。它使用文件第一个字段/列的数据进行索引。
!($1 in n)
如果第一个字段中的数据尚未分配新标签/名称,则为 true。