Verteilen eines Skripts: Soll ich / bin / gawk oder / usr / bin / gawk für shebang verwenden?

12

Ist gawk normalerweise in / bin oder / usr / bin? Ich würde mitgehen, #!/usr/bin/env gawkaber dann kann ich keine Argumente verwenden. Im Moment benutze ich #!/bin/gawk -f. Das Skript ist sehr lang und enthält viele einfache Anführungszeichen und funktioniert mit stdin.

Das GNU Awk-Handbuch enthält Abschnitt 1.1.4 Ausführbare awk-Programme, in denen in seinem Beispiel #! / Bin / awk verwendet wird.

Beachten Sie, dass auf vielen Systemen awkin /usr/binstatt statt in gefunden werden kann /bin. Vorbehalt Emptor.

Was machen die meisten Leute? Ich habe gelesen, dass sed angeblich in / bin standardisiert ist, während Perl angeblich in / usr / bin standardisiert ist (dieselbe Seite wie sed link, aber ich kann keinen dritten Link für diesen Beitrag erstellen). Was ist mit awk / gawk? Weiß jemand, was häufiger oder beliebter ist?

user2672807
quelle
Warum benutzt du -f? Ist das nicht /bin/gawkgenug Auch dies relevant sein könnte.
Terdon

Antworten:

7

Shebang sollte nicht so flexibel sein . Es kann Fälle geben, in denen ein zweiter Parameter funktioniert . Ich denke, FreeBSD ist einer davon.

Gawk und die meisten Dienstprogramme, die mit dem Betriebssystem geliefert werden, werden voraussichtlich verfügbar sein /usr/bin/.

In den älteren UNIX-Tagen war es üblich, /usr/über NFS oder ein weniger teures Medium zu mounten, um lokalen Speicherplatz und Kosten pro Workstation zu sparen. /bin/sollte alles haben, was zum Booten im Einzelbenutzermodus benötigt wird . Da /usr/es nicht auf einem zuverlässigen Medium installiert war, /bin/enthielt es genügend Dienstprogramme, um es für die allgemeine Verwaltung und Fehlerbehebung benutzerfreundlich genug zu machen.

Dies wurde ursprünglich unter Linux vererbt, aber da Speicherplatz kein Problem mehr darstellt und sich in den meisten Fällen /usr/im Root-Dateisystem befindet, besteht der aktuelle Trend darin, alles zu verschieben /usr/bin(zumindest in der Linux-Welt). Daher wird erwartet, dass die meisten von einer Distribution installierten Dienstprogramme dort zu finden sind. Selbst die grundlegenden Werkzeuge, wie cp, rm, lsusw. (na ja, noch nicht).

In Bezug auf die Shebang-Wahl. Traditionell müssen Administratoren oder Benutzer dies entsprechend ihrer Umgebung bearbeiten. Für alle Entwickler, in anderen Leuten Systeme kennen, könnte der Dolmetscher überall im Dateisystem (zB /usr/local/bin, /opt/gawk-4.0.1/bin). Ordnungsgemäß gepackte Skripte (rpm, deb usw.) sind entweder von einem Distributionspaket abhängig (dh der Interpreter hat einen bekannten Speicherort) oder von einem Konfigurationsskript, das den richtigen Hashbang während der Installation einrichtet.

forcefsck
quelle
14

Wenn Sie dem Befehl keine Argumente übergeben müssen, #!/usr/bin/env gawkist dies der richtige Weg. Viele Kernel (einschließlich Linux) akzeptieren jedoch nur ein einziges Argument für Shebang-Programme.

Andernfalls können Sie ein Polyglot- Programm erstellen , das sowohl ein Shell-Wrapper als auch das awk-Skript ist. Hier ist eine für awk.

#!/bin/sh
true + /; exec gawk -f "$0"; exit; / {}
# awk script starts here

Shell-Analyse:

  • true + /;- der Befehl true(der nichts tut) mit zwei inerten Argumenten +und /.
  • Der Anruf bei gawk. Dies kann jedes Shell-Snippet sein, das keine Zeilenumbrüche enthält und in dem Schrägstriche geschrieben sind \/(die Shell hat nichts dagegen, außer in Anführungszeichen).
    Der Aufruf wird verwendet exec, um die Shell durch gawk zu ersetzen, anstatt gawk als Unterprozess auszuführen.
  • exit;- Verlassen Sie die Schale, falls kein Gawk gefunden wurde. Alles, was danach passiert, wird ignoriert, außer dass es eine gültige Shell-Syntax sein sollte, falls die Shell versucht, die gesamte Zeile zu analysieren, bevor sie mit der Ausführung beginnt.

Awk-Analyse:

  • Das Bit zwischen Schrägstrichen ist ein regulärer Ausdruck.
  • true + /REGEX/- ein Zustand. trueist eine undefinierte Variable, daher ist ihr numerischer Wert 0, nicht dass es darauf ankommt.
  • {} - Wenn diese Bedingung erfüllt ist, tun Sie nichts.
Gilles 'SO - hör auf böse zu sein'
quelle
5

Gilles 'Lösungsvorschlag ist in der Tat ein sehr guter Ansatz (endlich den Ruf, in seinem Beitrag abzustimmen :)).

Soweit ich den execBefehl verstehe , macht er das exitRecht danach auf jeden Fall unnötig, tatsächlich nicht erreichbar, da der Shell-Prozess durch ersetzt wird awk.

Um dem awkSkript den Zugriff auf seine Aufrufparameter zu ermöglichen, würde ich außerdem einige Änderungen an der vorgeschlagenen Lösung vorschlagen:

#!/bin/sh
true + /; exec -a "$0" gawk -f "$0" -- "$@"; / {}
# awk script starts here

Das -a "$0"ermöglicht dem Skript den Zugriff auf seinen Aufrufnamen, andernfalls erhält es immer ein awkoder, gawkwenn auf die ARGV[0]Variable zugegriffen wird. In ähnlicher Weise "$@"ermöglicht das Skript dem Zugriff auf die verbleibenden Parameter im ARGV[1...N]Array, und das --vorhergehende ermöglicht es dem Skript, -<something>Argumente zu empfangen , ohne dass Gawk sie interpretiert.

Eine Sache, an die Sie sich erinnern / die Sie berücksichtigen sollten, ist das Hinzufügen einer exit(0);Anweisung am Ende des BEGIN { ... }Blocks des awkSkriptprogramms. Andernfalls awkwerden alle Parameter bedroht, die als Eingabedateien an das Skript übergeben werden. (Bitte beachten Sie, dass es überhaupt nichts mit der exitAnweisung zu tun hat, die wir aus der true + ...Zeile entfernt haben. Dies war eine nicht erreichbare Shell-Anweisung, während sich dieser vorgeschlagene Exit im awk-Code befindet.)

Marcelo
quelle
Das exit(0)war sehr nützlich! Für Macos-Benutzer gilt Folgendes: Ein guter tragbarer awk shebang ist nicht leicht zu finden.
Seamus