2013-07-24 12 views
8

Ich habe ein awk-Skript, das nach vielen möglichen Mustern sucht und etwas für jedes Muster tut. Ich möchte, dass etwas getan wird, wenn keines der Muster übereinstimmt. also etwa so:awk: "Standard" Aktion, wenn kein Muster gefunden wurde?

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

Wo natürlich die „STANDARD“ -Linie ist keine awk Syntax und ich möchte wissen, ob es eine solche Syntax ist (wie in der Regel gibt es in swtich/Case-Anweisungen in vielen Programmiersprachen).

Natürlich kann ich nach jeder Aktion immer einen "next" -Befehl hinzufügen, aber das ist mühsam, wenn ich viele Aktionen habe, und noch wichtiger, es verhindert, dass ich die Zeile mit zwei oder mehr Mustern abgleichen kann.

Antwort

11

Sie könnten das Spiel invertieren die Negation-Operator ! so etwas wie:

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

Aber das ist ziemlich böse für n>2. Alternativ können Sie auch ein Flag verwenden:

{f=0} 
/pattern 1/ {action 1;f=1} 
/pattern 2/ {action 2;f=1} 
... 
/pattern n/ {action n;f=1} 
f==0{default action} 
1

Es gibt keine "wartungsfreie" Lösung für einen DEFAULT-Zweig in awk.

Die erste Möglichkeit, die ich vorschlagen würde, besteht darin, jeden Zweig einer Musterübereinstimmung mit einer 'nächsten' Anweisung abzuschließen. Es ist also wie ein Break-Statement. Fügen Sie am Ende eine letzte Aktion hinzu, die mit allem übereinstimmt. Es ist also die DEAFULT-Filiale.

Die andere Möglichkeit wäre: ein Flag für jeden Zweig, der eine Musterübereinstimmung hat (das heißt Ihre Nicht-Standard-Verzweigungen) z.B. Starten Sie Ihre Aktionen mit NONDEFAULT = 1;

Fügen Sie eine letzte Aktion am Ende hinzu (die Standardverzweigung) und definieren Sie eine Bedingung NONDEFAULT == 0, die in einer reg-Ausdrucksmatch eingefügt wird.

+0

Abgesehen von dem Fehler, mit 'next' vorzuschlagen, unterscheidet sich das von meiner Antwort wie? –

+0

Hoppla - dein Recht - Entschuldigung. – tue

7

GNU awk hat switch-Anweisungen:

$ 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 

Alternativ mit jedem 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 

Verwenden Sie die "Pause" oder "weiter" wie/wann Sie wollen, so wie in anderen Programmiersprachen Sprachen.

Oder, wenn Sie einen Flag mit:

$ 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 

Es ist nicht exaclty die gleiche Semantik wie ein echte „default“ aber so ist es wie Nutzung, die irreführend sein könnte. Ich würde normalerweise nicht befürworten, alle Großbuchstaben-Variablennamen zu verwenden, aber Kleinbuchstaben "Standard" würde mit dem Gawk-Schlüsselwort kollidieren, so dass das Skript nicht tragbar wäre, um in Zukunft zu gaffen.

0

Eine ziemlich saubere, tragbare Problemumgehung wird unter Verwendung einer if Anweisung:

Statt:

pattern1 { action1 } 

pattern2 { action2 }  
... 

man folgendes verwenden:

{  
    if (pattern1) { action1 } 

    else if (pattern2) { action2 } 

    else { here is your default action } 
} 

Wie oben erwähnt, GNU awk hat Switch-Anweisungen, aber andere awk Implementierungen nicht, so würde Schalter nicht tragbar sein.

Verwandte Themen