2010-08-13 11 views

risposta

15

Gli script di shell vengono analizzati riga per riga durante l'esecuzione, quindi è necessario assicurarsi che l'esecuzione non raggiunga mai i dati che si desidera proteggere. Si potrebbe fare questo, per esempio:

# Some shell code... 

exit 

[data (possibly binary) goes here] 

Per effettivamente leggere questi dati dal vostro script, è possibile utilizzare un po 'di magia sed per estrarre tutto ciò dopo la prima riga che contiene solo __DATA__, quindi memorizzare l'output di tale sed in una variabile. Ecco un esempio:

#!/bin/sh 

data=$(sed '0,/^__DATA__$/d' "$0") 
printf '%s\n' "$data" 

exit 

__DATA__ 
FOO BAR BAZ 
LLAMA DUCK COW 

Se si salva questo script come test-data.sh e renderlo eseguibile, è possibile eseguire e ottenere il seguente output:

$ ./test-data.sh 
FOO BAR BAZ 
LLAMA DUCK COW 
+0

questo è bello, qualcuno può spiegare per favore come funziona? Non ho capito 'data = $ (sed '0,/^ __ DATA __ $/d'" $ 0 ")' – rodee

+0

Esegui il comando 'sed' e dalla riga 0 alla riga corrispondente a __DATA__, elimina la riga. Il resto verrà stampato. $ 0 è questo script, il file da leggere che contiene i dati. – mpersico

+0

Attenzione, però; se stai eseguendo il sourcing nel tuo script, non solo eseguendolo, allora '$ 0' è il tuo nome shell e il tuo' exit' uscirà dall'intera sessione. Sostituisci '$ 0' con' $ {BASH_ARGV [0]} 'e' exit' con 'return'. – mpersico

3

Prima di tutto di perl "__DATA__" Pragma è una modo di fornire input a $ _ senza specificare un file. Non esiste un equivalente in bash poiché non ha nulla di simile a $ _. Tuttavia è possibile fornire i dati direttamente in uno script bash con altri mezzi come variabili di impostazione esplicite, utilizzando documenti HERE, ecc.

Tuttavia non sono convinto che questo è ciò che si desidera fare. Sembra il tuo dopo una sorta di metodo di commento dei blocchi. È questo il caso?

+0

Sì, ma anche l'altra parte è interessante. Quindi accetterò la soluzione di uscita anche se non è bella come __DATA__ perché dopo __DATA__ non c'è più sintassi di evidenziazione e __DATA__ stesso è più visibile nel codice che exit. Per la fornitura di dati, probabilmente sarei un documento QUI poiché è più facile da ricordare rispetto alla proposta di bcat. –

+1

Sì, l'utilizzo di un heredoc è quasi certamente la soluzione migliore per fornire grandi quantità di dati a uno script. L'unica volta che userò la mia soluzione (oltre che come proof of concept) è se avessi bisogno di includere facilmente i dati in uno script di shell che potrebbe includere il terminatore heredoc. – bcat

+0

IIUC, impostando le variabili in modo esplicito e utilizzando heredocs avrà l'effetto di avere i dati giusto dab giusto nel mezzo del codice. La tecnica __DATA__ metterà tutti quei dati alla fine in modo che tu possa leggere il codice senza l'interrupt di contesto. IMO, l'utilizzo di questo per i dati NON è ottimale. Meglio leggere da una fonte esterna. MA, potrebbe essere appropriato per un test di auto-documentazione. Lo uso solo per le dichiarazioni USAGE come sopra. – mpersico

0

Questa è una tecnica utile se si desidera fornire informazioni sull'utilizzo del proprio script, ma non si vuole ingombrare la riga principale del codice con il testo della guida. È anche bello se vuoi fare riferimento all'utilizzo più di una volta. Per esempio, uno snippet da uno script di shell mio:

... 
declare OPTSARGS  
OPTSARGS=$(getoptp -o wh --long nopager,help -n myScript-- "[email protected]") 
status=$? 
if ((status != 0))  
then 
    printf '%s\n' "$(sed '0,/^__USAGE__$/d' $0)" 
    exit $status 
fi 
eval set -- "$OPTSARGS" 
while true 
do 
    case "$1" in 
     -w) diffargs="$diffargs -w"; shift;; 
     --nopager) pager=cat; shift;; 
     --) shift; break ;; ## end of opts, remaining $*, if any, are args 
     -h | --help) 
      printf '%s\n' "$(sed '0,/^__USAGE__$/d' $0)" 
      exit 0;; 
     *) 
      echo "Internal error!" 
      printf '%s\n' "$(sed '0,/^__USAGE__$/d' $0)" 
      exit 1;; 
    esac 
done 

... 

echo "Done" 
exit 0 

__USAGE__ 
myScript [-w] [--nopager] [file [file...] ] 

Some description goes here. 

     -w - Do not compare whitespace 
--nopager - Do not pass the output through 'less' 
Problemi correlati