15

我有一个 awk 脚本,它检查很多可能的模式,为每个模式做一些事情。我想要做点什么,以防没有匹配的模式。即是这样的:

/pattern 1/ {action 1}
/pattern 2/ {action 2}
...
/pattern n/ {action n}
DEFAULT {default action}

当然,“DEFAULT”行没有 awk 语法,我想知道是否有这样的语法(就像许多编程语言中的 swtich/case 语句中通常存在的那样)。

当然,我总是可以在每个动作之后添加一个“下一个”命令,但如果我有很多动作,这会很乏味,更重要的是,它会阻止我将行匹配到两个或多个模式。

4

5 回答 5

15

您可以使用否定运算符反转匹配, !例如:

!/pattern 1|pattern 2|pattern/{default action}

但这对n>2. 或者,您可以使用标志:

{f=0}
/pattern 1/ {action 1;f=1}
/pattern 2/ {action 2;f=1}
...
/pattern n/ {action n;f=1}
f==0{default action}
于 2013-07-24T10:23:56.923 回答
11

GNU awk 有 switch 语句:

$ cat tst1.awk
{
    switch($0)
    {
    case /a/:
        print "found a"
        break

    case /c/:
        print "found c"
        break

    default:
        print "hit the default"
        break
    }
}

$ cat file
a
b
c
d

$ gawk -f tst1.awk file
found a
hit the default
found c
hit the default

或者使用任何 awk:

$ cat tst2.awk
/a/ {
    print "found a"
    next
}

/c/ {
    print "found c"
    next
}

{
    print "hit the default"
}

$ awk -f tst2.awk file
found a
hit the default
found c
hit the default

就像在其他编程语言中一样,在需要时使用“break”或“next”。

或者,如果您喜欢使用标志:

$ cat tst3.awk
{ DEFAULT = 1 }

/a/ {
    print "found a"
    DEFAULT = 0
}

/c/ {
    print "found c"
    DEFAULT = 0
}

DEFAULT {
    print "hit the default"
}

$ gawk -f tst3.awk file
found a
hit the default
found c
hit the default

不过,它与真正的“默认”的语义并不完全相同,因此这样的用法可能会产生误导。我通常不提倡使用全大写的变量名,但小写的“默认”会与 gawk 关键字发生冲突,因此该脚本将来无法移植到 gawk。

于 2013-07-24T14:16:29.380 回答
5

正如上面 tue 所提到的,我对 awk 中标准方法的理解是将 next 放在每个备选方案上,然后在没有模式的情况下进行最终操作。

/pattern1/ { action1; next }
/pattern2/ { action2; next }
{ default-action }

下一条语句将保证不再为所讨论的行考虑模式。如果前面的那些没有发生,那么默认操作总是会发生(感谢所有接下来的语句)。

于 2020-04-05T06:39:42.417 回答
0

awk 中的 DEFAULT-Branch 没有“免维护”解决方案。

我建议的第一种可能性是用“下一个”语句完成模式匹配的每个分支。所以它就像一个break语句。在最后添加一个匹配所有内容的最终操作。所以它是 DEAFULT 分支。

另一种可能性是:为每个具有模式匹配的分支(即您的非默认分支)设置一个标志,例如以 NONDEFAULT=1 开始您的操作;

在末尾添加最后一个操作(默认分支)并定义条件 NONDEFAULT==0 代替 reg 表达式匹配。

于 2013-07-24T10:38:09.483 回答
0

一个相当干净、可移植的解决方法是使用以下if语句:

代替:

pattern1 { action1 }

pattern2 { action2 }    
...

可以使用以下内容:

{    
    if ( pattern1 ) { action1 }

    else if ( pattern2 ) { action2 }

    else { here is your default action }
}

如上所述,GNUawk有 switch 语句,但其他awk实现没有,所以使用 switch 是不可移植的。

于 2014-06-13T13:29:34.247 回答