Programmierbares Erkennen des Awk-Geschmacks (z. B. Gawk vs Nawk)

8

Ich verwende eine Befehlszeilenanwendung, die im Wesentlichen eine Sammlung von Bash-Shell-Skripten ist. Die Anwendung wurde für die Ausführung unter BSD / OSX und auch unter Linux geschrieben. Eines der Skripte basiert auf awk. Es enthält zwei awk-Befehle: einen für nawk (die Standard-BSD-awk-Implementierung) und einen für gawk (die GNU-awk-Implementierung).

Die beiden fraglichen awk-Befehle sind nicht mit den verschiedenen Umgebungen kompatibel. Insbesondere der Befehl nawk schlägt fehl, wenn er mit gawk ausgeführt wird. Das Skript überprüft den Kernelnamen (dh uname -s), um die Hostumgebung zu bestimmen, und führt dann den entsprechenden Befehl awk aus. Ich arbeite jedoch lieber unter Mac OS X mit den installierten GNU-Kerndienstprogrammen, sodass das Skript nicht ordnungsgemäß ausgeführt wird.

Während ich darüber nachdachte, wie dieser Fehler am besten behoben werden kann, kam mir der Gedanke, dass es schön wäre zu wissen, wie man programmgesteuert zwischen verschiedenen Varianten der gängigen Befehlszeilenprogramme unterscheidet, vorzugsweise auf relativ robuste und tragbare Weise.

Ich habe festgestellt, dass nawk das Flag '-V' zum Drucken der Versionsinformationen nicht akzeptiert. Daher habe ich mir gedacht, dass so etwas wie das Folgende funktionieren sollte:

awk -V &>/dev/null && echo gawk || echo nawk

Eine andere Variante könnte sein:

awk -Wversion &>/dev/null && echo gawk || echo nawk

Dies scheint in meinen beiden Testumgebungen (OS X und CentOS) zu funktionieren. Hier sind meine Fragen:

  • Ist das der beste Weg?
  • Gibt es eine Möglichkeit, dies zu erweitern, um andere Variationen von awk (z. B. mawk, jawk usw.) zu handhaben?
  • Lohnt es sich überhaupt, sich Gedanken über andere Versionen von awk zu machen?

Ich sollte auch erwähnen, dass ich sehr wenig über awk weiß.

igal
quelle
Wenn der Befehl awk nicht extrem kompliziert ist oder auch nicht, können Sie ihn auf Perl oder etwas anderes portieren, das einheitlich ist.
Wildcard
Lassen Sie awk Version von awk -Wvanstelle der Host-Umgebung sehen
Costas
1
Mein awk ist sehr schwach, aber ich glaube, dass es ziemlich einfach ist. Ich habe es tatsächlich schon in purer Bash umgeschrieben. Dies ist jedoch eine dieser Situationen, in denen ich mehr daran interessiert bin, meine Neugier zu befriedigen, als das ursprüngliche Problem tatsächlich zu lösen.
igal
@Costas So etwas ist mir tatsächlich eingefallen, aber ich war mir nicht sicher, wie zerbrechlich es sein könnte. Ich weiß sehr wenig über awk. Ich habe meine aktuelle Lösung zu meinem Beitrag hinzugefügt.
igal
1
Eine Alternative besteht darin, zu ignorieren, welche Version von awkverwendet wird, und stattdessen Code gemäß der POSIX-Spezifikation zu verwenden.
Chepner

Antworten:

7
if awk --version 2>&1 | grep -q "GNU Awk"
then
    awk 'BEGIN {print "I am GNU Awk"}'

elif awk -Wv 2>&1 | grep -q "mawk"
then
    awk 'BEGIN {print "I am mawk"}'

else
    awk 'BEGIN {print "I might be nawk, might not be"}'
fi

Alternativ ist test is awk eine symbolische Verbindung:

awk=$( command -v awk )
[[ -L $awk ]] && readlink $awk # make some decision about the result of that
Glenn Jackman
quelle
Dieser ist in Ordnung ... aber es gibt einige Variationen (schwer zu unterscheiden) für Old-Awk-, Nawk- und die neueren BWK-Versionen. Für diese kann ein Beispielskript angepasst werden .
Thomas Dickey
3

Versuchen Sie es mit dem whichBefehl und verwenden Sie den Exit-Code.

which nawk
if [[ $? == 0 ]]; then
    command="nawk"
else
    command="gawk"
fi

Formatieren Sie dann Ihr Skript, um die Variable als Befehl zu verwenden

$command '{print $1}` 

würde gelesen werden als

nawk '{print $1}`

wenn whichnawk findet. Sonst würde es verwendengawk

Kip K.
quelle
1
da commandist ein bash builtin Sie einen anderen Namen für die Variable verwenden möchten, und Sie können auch die unglaublich detaillierte Antwort auf die Frage , warum für viele Muscheln dort sehen möchten , bessere Alternativen sind whichbei unix.stackexchange.com/a/85250/109842
Eric Renouf
1

GNU Awk wird häufig als gawk, awkals Symlink dazu auf Systemen installiert , auf denen GNU die Standardeinstellung ist. Ich würde vermuten, dass dies auf BSD- und OS X-Systemen der Fall ist, da sie bereits ihre eigenen haben awk.

if gawk '{ exit; }' < /dev/null 2> /dev/null
then
    echo "gawk available"
else
    echo "gawk not available"
fi
James Sneeringer
quelle
Danke für deinen Beitrag. Dies ist eine gute Idee, und Sie haben Recht, dass dies unter OS X bei mir der Fall ist. Aber ich hatte sozusagen auf eine intrinsische Lösung gehofft.
igal
0

Ein dreckiger Hack

if nawk 'BEGIN { nawk-only-function() ;}' 
then 
   nawk -f nfile.awk ...
else 
   gawk -f gfile.awk ...
fi
  • wo nawk-only-function() gibt es nur aufnawk
Archemar
quelle
-2

Ich würde wahrscheinlich versuchen, das Makro AC_PROG_AWK m4 in autoconf zu missbrauchen, um eines auszuwählen und es entsprechend zu ordnen. Es ist wahrscheinlich übertrieben

ssta
quelle
Könnten Sie etwas bearbeiten , um etwas detaillierter zu erfahren, wie Sie dieses Makro für dieses Szenario verwenden würden?
Michael Homer
Es sagt nicht wirklich, welche es gefunden hat, sondern sucht einfach nach awk-Implementierungen und wählt eine basierend auf ihrem Namen aus.
Thomas Dickey