È stato utile?

Soluzione

Questo sembra funzionare per me con (g) awk.

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


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

Si noti la #! corre /bin/sh, quindi questo script viene prima interpretata come uno script di shell.

Inizialmente, ho semplicemente provato "exec" "/usr/bin/gawk" "--re-interval" "-f" "$0" "$@", ma awk considerato che come un comando e stampato fuori ogni linea di input incondizionatamente. È per questo che ho messo nel arbitrary_long_name==0 - si suppone a fallire tutto il tempo. Si potrebbe sostituirlo con qualche stringa senza senso. In sostanza, ero alla ricerca di un falso-condizione in awk che non influenzare negativamente lo script di shell.

Nello script shell, il arbitrary_long_name==0 definisce una variabile denominata arbitrary_long_name e imposta uguale a =0.

Altri suggerimenti

La linea shebang non è mai stata specificata come parte di POSIX, SUS, LSB o qualsiasi altra specifica. Per quanto ne so, si è nemmeno stata adeguatamente documentata.

V'è un consenso di massima su ciò che fa: prendere tutto tra il ! e \n e exec esso. Il presupposto è che tutto tra il ! ed il \n è un percorso assoluto completo per l'interprete. Non c'è consenso su ciò che accade se contiene spazi bianchi.

  1. Alcuni sistemi operativi semplicemente trattare la cosa intera come il percorso. Dopo tutto, nella maggior parte dei sistemi operativi, spazi o trattini sono legali in un percorso.
  2. Alcuni sistemi operativi divisi in spazi e trattano la prima parte, il percorso per l'interprete e il resto come singoli argomenti.
  3. Alcuni sistemi operativi divisi al prima spazi e trattare la parte anteriore come il percorso per l'interpeter e il resto come un solo argomento (che è quello che si sta vedendo ).
  4. Alcuni addirittura non supportano linee Shebang a tutti .

Per fortuna, 1. e 4. sembra che sia morto, ma 3. è abbastanza diffusa, in modo semplicemente non si può contare sul fatto di poter passare più di un argomento.

E dal momento che la posizione dei comandi è, inoltre, non specificato in POSIX o SUS, in genere si usa up che singolo argomento passando dell'eseguibile nome per env in modo che è lattina determinare la posizione del file eseguibile; per esempio:.

#!/usr/bin/env gawk

[Ovviamente, questa ancora assume una particolare percorso per env, ma ci sono solo pochi sistemi in cui vive in /bin, quindi questo è generalmente sicura. La posizione di env è molto più standardizzato rispetto alla posizione del gawk o peggio ancora qualcosa di simile python o ruby o spidermonkey.]

Il che significa che non si può effettivamente usare qualsiasi a tutti .

mi sono imbattuto lo stesso problema, senza soluzione apparente a causa del modo in cui gli spazi bianchi sono trattati in uno shebang (almeno su Linux).

Tuttavia, si può passare diverse opzioni in una baracca, nella misura in cui sono opzioni brevi e possono essere concatenati (il modo in cui GNU).

Per esempio, non si può avere

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

, ma si può avere

#!/usr/bin/foo -if

Ovviamente, che funziona solo quando le opzioni sono equivalenti a breve e prendere senza argomenti.

Sotto Cygwin e Linux tutto dopo il percorso della baracca viene analizzato per il programma come un argomento.

E 'possibile incidere intorno a questo utilizzando un altro script awk all'interno della baracca:

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

Questo eseguirà {system("/usr/bin/gawk --re-interval -f " FILENAME); exit} in awk.
E questo eseguirà /usr/bin/gawk --re-interval -f path/to/your/script.awk nei vostri sistemi shell.

Anche se non è esattamente portatile, a partire da coreutils 8.30 e in base alla relativa documentazione si sarà in grado di utilizzare:

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

Quindi, dato:

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

si otterrà:

% ./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'

e nel caso in cui siete curiosi showargs è:

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

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

qui .

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

Il guscio sopra shebang trucco è più portabile di /usr/bin/env.

Nel manuale gawk (http://www.gnu.org/manual/gawk/gawk.html), alla fine della sezione 1.14 Si raccomanda di utilizzare solo un unico argomento quando si esegue gawk da una linea di shebang. Si dice che il sistema operativo tratterà tutto dopo il percorso di gawk come un unico argomento. Forse c'è un altro modo per specificare l'opzione --re-interval? Forse il vostro script può fare riferimento la shell nella linea shebang, gawk eseguito come un comando e includere il testo del vostro script come un "here document".

Perché non usare bash e gawk per sé, per saltare la baracca passato, letto la sceneggiatura, e passarla come un file a una seconda istanza di 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
}

(- lo stesso si potrebbe naturalmente anche essere realizzato con per esempio sed o tail, ma penso che ci sia un certo tipo di bellezza dipendente solo da bash e gawk stesso;)

Solo per divertimento:. V'è la seguente soluzione abbastanza strano che reindirizza stdin e il programma attraverso descrittori di file 3 e 4. Si potrebbe anche creare un file temporaneo per lo script

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

Una cosa è fastidiosa di questo:. Il guscio fa di espansione variabile sullo script, quindi bisogna citare ogni $ (come fatto nella seconda riga dello script) e, probabilmente, più di questo

Per una soluzione portatile, uso awk piuttosto che gawk, invocare la Bourne shell standard (/bin/sh) con la faccenda, e invocare awk direttamente, passando il programma sulla riga di comando come qui documentare piuttosto che attraverso stdin:

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

Nota: non -f argomento per awk. Che lascia stdin disponibile per awk per leggere l'input da. Supponendo di avere gawk installato e sul PATH, che consente di ottenere tutto quello che penso si stavano cercando di fare con il tuo esempio originale (supponendo che voleva che il contenuto del file di essere lo script awk e non l'ingresso, che a mio avviso il tuo approccio faccenda avrebbe trattato come).

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top