Distribuire uno script: dovrei usare / bin / gawk o / usr / bin / gawk per shebang?


12

Di solito gawk è in / bin o / usr / bin? Vorrei andare con #!/usr/bin/env gawkma poi non posso usare argomenti. In questo momento sto usando #!/bin/gawk -f. Lo script è molto lungo e contiene molte virgolette singole e funziona con stdin.

Il manuale di GNU Awk ha la sezione 1.1.4 Programmi awk eseguibili in cui usa #! / Bin / awk nel suo esempio ma continua dicendo:

Si noti che su molti sistemi è awkpossibile trovare /usr/bininvece di in /bin. Caveat Emptor.

Cosa fanno la maggior parte delle persone? Ho letto che sed è apparentemente standardizzato in / bin mentre perl è presumibilmente standardizzato in / usr / bin (stessa pagina del link sed ma non mi permettono di creare un terzo link per questo post). Che dire di awk / gawk? Qualcuno sa quale è più comune o popolare?


Perché si usa -f? Non è /bin/gawkabbastanza? Inoltre, questo potrebbe essere rilevante.
terdon

Risposte:


7

Shebang non doveva essere così flessibile . Ci possono essere alcuni casi in cui funziona un secondo parametro , penso che FreeBSD sia uno di questi.

gawk e la maggior parte delle utility fornite con il sistema operativo dovrebbero essere presenti /usr/bin/.

Nei vecchi giorni UNIX, era comune /usr/montare su NFS o alcuni supporti meno costosi per risparmiare spazio su disco locale e costi per workstation. /bin/doveva avere tutto il necessario per l'avvio in modalità utente singolo . Dato che /usr/non era montato su un supporto affidabile, /bin/includeva abbastanza utility da renderlo abbastanza amichevole per l'amministrazione generale e la risoluzione dei problemi.

Questo è stato ereditato inizialmente in Linux, ma poiché lo spazio su disco non è più un problema e nella maggior parte dei casi si /usr/trova nel filesystem di root, l'attuale tendenza è quella di spostare tutto /usr/bin(almeno nel mondo Linux). Quindi ci si aspetta che la maggior parte delle utility installate da una distribuzione si trovi lì. Anche la maggior parte dei servizi di base, come cp, rm, lsetc (beh, non ancora).

Per quanto riguarda la scelta shebang. Tradizionalmente, questo è qualcosa che gli amministratori o gli utenti devono modificare in base al loro ambiente. Per tutti uno sviluppatore sa, in sistemi di altre persone, l'interprete potrebbe essere ovunque nel filesystem (ad esempio /usr/local/bin, /opt/gawk-4.0.1/bin). Gli script correttamente impacchettati (rpm, deb ecc.) Hanno una dipendenza da un pacchetto distro (cioè l'interprete ha una posizione nota) o uno script di configurazione che imposta l'hashbang corretto durante l'installazione.


14

Se non hai bisogno di passare argomenti al comando, allora #!/usr/bin/env gawkè la strada da percorrere, tuttavia molti kernel (incluso Linux) accettano solo un singolo argomento per i programmi shebang.

Altrimenti, puoi creare un programma poliglotta che è sia un wrapper di shell che lo script awk. Eccone uno per awk.

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

Analisi della shell:

  • true + /;- il comando true(che non fa nulla) con due argomenti inerti +e /.
  • La chiamata a gawk. Potrebbe trattarsi di qualsiasi frammento di shell che non contenga nuove righe e dove vengano scritte le barre \/(alla shell non importa se non tra virgolette).
    La chiamata usa execper sostituire la shell con gawk invece di eseguire gawk come sottoprocesso.
  • exit;- esci dalla shell, nel caso in cui non fosse stato trovato gawk. Qualunque cosa successiva viene ignorata, tranne per il fatto che dovrebbe essere una sintassi della shell valida nel caso in cui la shell cerchi di analizzare l'intera riga prima di iniziare a eseguirla.

Analisi Awk:

  • Il bit tra le barre è un'espressione regolare.
  • true + /REGEX/- una condizione. trueè una variabile indefinita, quindi il suo valore numerico è 0, non che sia importante.
  • {} - Se detta condizione è valida, non fare nulla.

5

La soluzione proposta da Gilles è davvero un ottimo approccio (finalmente ha la reputazione di votare nel suo post :)).

In ogni caso, per quanto ho capito il execcomando, rende il exitdiritto subito dopo non necessario, in realtà irraggiungibile, poiché il processo di shell viene sostituito da awk.

Inoltre, per consentire allo awkscript di accedere ai parametri di invocazione, suggerirei alcune modifiche nella soluzione proposta:

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

Ciò -a "$0"consente allo script di avere accesso al suo nome di invocazione, altrimenti otterrà sempre un awko gawkquando accederà alla ARGV[0]variabile. Allo stesso modo, "$@"consente allo script di accedere ai parametri rimanenti ARGV[1...N]nell'array e il --precedente consente allo script di ricevere -<something>argomenti senza che Gawk li interpreti.

Una cosa da ricordare / considerare è aggiungere exit(0);un'istruzione alla fine del BEGIN { ... }blocco del awkprogramma di script, altrimenti awkminaccia tutti i parametri passati allo script come file di input. (Si noti che non ha assolutamente nulla a che fare con l' exitaffermazione che abbiamo rimosso dalla true + ...riga, questa era un'istruzione shell irraggiungibile mentre questa uscita suggerita è nel codice awk).


È exit(0)stato molto utile! Inoltre, per gli utenti di macos, guarda questo riassunto: un buon shekang awk portatile non è facile da trovare.
Seamus,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.