Frage

würde Ich mag eine gaffen Skript mit --re-interval mit einem shebang auszuführen. Der "naive" Ansatz von

#!/usr/bin/gawk --re-interval -f
... awk script goes here

nicht funktioniert, da glotzen mit dem ersten Argument "--re-interval -f" genannt wird (nicht um den Leerzeichen aufgeteilt), die es nicht versteht. Gibt es eine Abhilfe für das?

Natürlich können Sie entweder rufen nicht gaffen direkt, sondern in einen Shell-Skript wickeln, die das erste Argument teilt, oder einen Shell-Skript, dass dann ruft gaffen und setzen Sie das Skript in einer anderen Datei, aber ich frage mich, ob es etwas war Art und Weise, dies zu tun in einer Datei.

Das Verhalten von Linien unterscheidet sich von System zu System sheBANG - zumindest in Cygwin tut es nicht teilen Sie die Argumente von Whitespaces. Ich kümmere nur darum, wie es auf einem System zu tun, dass verhält sich wie das; das Skript nicht tragbar sein soll.

War es hilfreich?

Lösung

Das scheint für mich arbeiten mit (g) awk.

#!/bin/sh
arbitrary_long_name==0 "exec" "/usr/bin/gawk" "--re-interval" "-f" "$0" "$@"


# The real awk program starts here
{ print $0 }

Beachten Sie die #! läuft /bin/sh, so dass dieses Skript zunächst als ein Shell-Skript interpretiert wird.

Zuerst habe ich einfach versucht "exec" "/usr/bin/gawk" "--re-interval" "-f" "$0" "$@", aber awk behandelt, dass als Befehl und bedingungslos jede Eingabezeile ausgedruckt. Deshalb habe ich in der arbitrary_long_name==0 setzen - es soll die ganze Zeit zum Scheitern verurteilt. Man könnte es mit etwas Kauderwelsch Zeichenfolge ersetzen. Im Grunde war ich die Suche nach einem falsch-Zustand in awk, die nicht negativ auf das Shell-Script beeinflussen würden.

In dem Shell-Skript, das arbitrary_long_name==0 definiert eine Variable namens arbitrary_long_name und setzt es auf =0 entsprechen.

Andere Tipps

Die shebang Linie wird nie als Teil von POSIX angegeben, SUS, LSB oder einer anderen Spezifikation. AFAIK, es ist nicht einmal richtig dokumentiert worden.

Es gibt einen groben Konsens darüber, was es tut: Nehmen Sie alles zwischen den ! und den \n und exec es. Die Annahme ist, dass alles, was zwischen dem ! und der \n ist ein Full absoluter Pfad zum Interpreter. Es gibt keinen Konsens darüber, was passiert, wenn es Leerzeichen enthält.

  1. Einige Betriebssysteme behandeln einfach die ganze Sache als Pfad. Denn in den meisten Betriebssystemen, Leerzeichen oder Bindestriche in einem Pfad legal sind.
  2. Einige Betriebssysteme bei Leerzeichen aufgeteilt und behandeln den ersten Teil als Pfad zum Interpreter und der Rest als einzelne Argumente.
  3. aufgeteilt Einige Betriebssysteme auf der zuerst Leerzeichen und behandeln den vorderen Teil als Weg zum interpeter und den Rest als Single Argument (das ist, was Sie sehen ).
  4. Einige haben sogar nicht unterstützen shebang Linien an alle .

Zum Glück, 1. und 4. scheinen darauf gestorben, aber 3. ist ziemlich weit verbreitet, so dass Sie einfach nicht darauf vertrauen können mehr als ein Argument zu übergeben.

Und da die Lage der Befehle ist auch in POSIX oder SUS nicht angegeben ist, verwenden Sie in der Regel auf, dass einzelne Argument der ausführbaren vorbei name zu env, so dass es Dose bestimmen Sie den Speicherort der ausführbaren Datei; z.

#!/usr/bin/env gawk

[Offensichtlich ist dies noch nimmt einen bestimmten Weg für env, aber es gibt nur sehr wenige Systeme, bei denen es in /bin lebt, so ist dies im Allgemeinen sicher. Die Lage von env ist viel mehr standardisiert als die Lage von gawk oder noch schlimmer so etwas wie python oder ruby oder spidermonkey.]

Was bedeutet, dass Sie nicht wirklich verwenden können alle Argumente an alle .

Ich kam in der gleichen Ausgabe, ohne offensichtliche Lösung wegen der Art, die mit Whitespaces in einem shebang behandelt werden (zumindest unter Linux).

Sie können jedoch mehrere Optionen in einem shebang passieren, solange sie sind Short-Optionen und sie können sein verketteten (die GNU-Weg).

Zum Beispiel können Sie nicht

haben
#!/usr/bin/foo -i -f

Sie können sich jedoch

#!/usr/bin/foo -if

Offensichtlich das funktioniert nur, wenn die Optionen kurze Äquivalente haben und keine Argumente haben.

Unter Cygwin und Linux alles nach dem Weg des shebang des Programm als ein Argument analysiert wird.

Es ist möglich, dies in der shebang unter Verwendung eines anderen awk Skript zu hacken um:

#!/usr/bin/gawk {system("/usr/bin/gawk --re-interval -f " FILENAME); exit}

Dies wird {system("/usr/bin/gawk --re-interval -f " FILENAME); exit} in awk auszuführen.
Und dies wird ausführen /usr/bin/gawk --re-interval -f path/to/your/script.awk in Ihren Systemen Shell.

Obwohl es nicht genau tragbar, beginnend mit coreutils 8,30 und nach seiner Dokumentation Sie in der Lage zu verwenden:

#!/usr/bin/env -S command arg1 arg2 ...

So gegeben:

$ cat test.sh
#!/usr/bin/env -S showargs here 'is another' long arg -e "this and that " too

Sie erhalten:

% ./test.sh 
$0 is '/usr/local/bin/showargs'
$1 is 'here'
$2 is 'is another'
$3 is 'long'
$4 is 'arg'
$5 is '-e'
$6 is 'this and that '
$7 is 'too'
$8 is './test.sh'

und falls Sie sind neugierig showargs ist:

#!/usr/bin/env sh
echo "\$0 is '$0'"

i=1
for arg in "$@"; do
    echo "\$$i is '$arg'"
    i=$((i+1))
done

Original Antwort href="https://unix.stackexchange.com/a/477651/4781">.

#!/bin/sh
''':'
exec YourProg -some_options "$0" "$@"
'''

Der Trick shebang oben Shell ist mehr tragbar als /usr/bin/env.

In der gaffen Handbuch (http://www.gnu.org/manual/gawk/gawk.html), das Ende des Abschnitts 1.14 beachten Sie, dass Sie nur ein einziges Argument verwenden sollte, wenn gaffen von einer shebang Linie. Er sagt, dass das O alles behandeln, nachdem der Pfad als ein einziges Argument gaffen. Vielleicht gibt es eine andere Möglichkeit, die --re-interval Option angeben? Vielleicht ist Ihr Skript kann die Shell in der Shebang-Zeile, lief gawk als Befehl ein, und schließen Sie den Text des Skripts als „hier Dokument“ verweisen.

Warum nicht bash verwenden und gawk selbst, vorbei an shebang zu überspringen, las das Drehbuch, und übergeben Sie es als eine Datei in eine zweite Instanz von gawk [--with-whatever-number-of-params-you-need]?

#!/bin/bash
gawk --re-interval -f <(gawk 'NR>3' $0 )
exit
{
  print "Program body goes here"
  print $1
}

(- das gleiche könnte natürlich auch mit z.B. sed oder tail erreicht werden, aber ich denke, es gibt eine Art von Schönheit nur auf bash abhängig und gawk selbst;)

Just for fun. Gibt es die folgende ziemlich seltsame Lösung ist, dass Umleitungen stdin und das Programm durch Filedeskriptoren 3 und 4. Sie auch eine temporäre Datei für das Skript erstellen könnten

#!/bin/bash
exec 3>&0
exec <<-EOF 4>&0
BEGIN {print "HALLO"}
{print \$1}
EOF
gawk --re-interval -f <(cat 0>&4) 0>&3

Eine Sache ist ärgerlich darüber. Die Schale auf der Skriptvariable Expansion der Fall ist, so dass Sie jede $ zu zitieren haben (wie in der zweiten Zeile des Skripts fertig) und wahrscheinlich mehr als das

Für eine tragbare Lösung, die Verwendung awk statt gawk, rufen Sie den Standard-Bourne-Shell (/bin/sh) mit Ihrem shebang und invoke awk direkt auf der Kommandozeile als hier das Programm vorbei dokumentieren, anstatt über stdin:

#!/bin/sh
gawk --re-interval <<<EOF
PROGRAM HERE
EOF

Hinweis: kein -f Argument awk. Das läßt stdin für awk verfügbar Eingabe von zu lesen. Angenommen, Sie gawk installiert und auf Ihrem PATH haben, erreicht, dass alles, was ich denke, Sie mit Ihrem ursprünglichen Beispiel vorhatten (vorausgesetzt, Sie den Dateiinhalt wollten der awk-Skript zu sein und nicht der Eingang, die ich Ihr shebang Ansatz denken wäre behandelt es wie).

scroll top