awk: действие" по умолчанию", если шаблон не был сопоставлен?

У меня есть скрипт awk, который проверяет множество возможных шаблонов, делая что-то для каждого шаблона. Я хочу, чтобы что-то было сделано в случае, если ни один из шаблонов не был сопоставлен. то есть что-то вроде этого:

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

где, конечно, строка "DEFAULT" не является синтаксисом awk, и я хочу знать, есть ли такой синтаксис (как обычно есть в операторах swtich/case на многих языках программирования).

конечно, я всегда могу добавить команду "next" после каждого действия, но это утомительно, если у меня много действий, и, что более важно, это мешает мне сопоставить линию с двумя или более шаблонами.

4 ответов


вы можете инвертировать совпадение с помощью оператора отрицания ! что-то вроде:

!/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}

GNU awk имеет операторы переключения:

$ cat tst1.awk
{
    switch()
    {
    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

это не точно такая же семантика, как истинный "по умолчанию", хотя это использование может ввести в заблуждение. Я бы обычно не выступал за использование всех имен переменных верхнего регистра, но нижний регистр "default" будет конфликтовать с ключевым словом gawk, чтобы скрипт не был переносимым для gawk в будущем.


нет решения "maintanance free" для ветви по умолчанию в awk.

первая возможность, которую я бы предложил, - это завершить каждую ветвь соответствия шаблону с помощью оператора "next". Это как заявление о перерыве. Добавьте последнее действие в конце, которое соответствует всему. Значит, это глухая ветвь.

другой возможностью: установите флаг для каждой ветви, которая имеет соответствие шаблону (т. е. ваши нестандартные ветви) например, начните свои действия с По умолчанию=1;

добавьте последнее действие в конце (ветвь по умолчанию) и определите условие NONDEFAULT==0 в соответствии с выражением reg.


довольно чистый, портативный обходной путь использует if о себе:

вместо:

pattern1 { action1 }

pattern2 { action2 }    
...

можно использовать следующие:

{    
    if ( pattern1 ) { action1 }

    else if ( pattern2 ) { action2 }

    else { here is your default action }
}

как упоминалось выше, GNU awk имеет операторы switch, но другие awk реализации не делают, поэтому использование коммутатора не будет портативным.