3 581
contributi
m (limite dei 30 KB... sigh...) |
(riscritta parte sulla redirezione (ma è ancora incompleta e mancano i file descriptor)) |
||
Riga 11: | Riga 11: | ||
Un nome di variabile ammette soltanto caratteri alfabetici (maiuscoli e minuscoli), l'underscore ('_') e numeri (non in prima posizione). E il suo contenuto si accede con <code>${nome}</code> oppure con la forma abbreviata <code>$nome</code>. | Un nome di variabile ammette soltanto caratteri alfabetici (maiuscoli e minuscoli), l'underscore ('_') e numeri (non in prima posizione). E il suo contenuto si accede con <code>${nome}</code> oppure con la forma abbreviata <code>$nome</code>. | ||
La forma abbreviata assume che il nome della variabile sia composto da tutti i caratteri validi incontrati. Per esempio <code>"$nome$cognome"</code> | La forma abbreviata assume che il nome della variabile sia composto da tutti i caratteri validi incontrati. Per esempio la concatenazione <code>"$nome$cognome"</code> è equivalente a <code>"${nome}${cognome}"</code>, ma <code>"$nome_$cognome"</code> non lo è a <code>"${nome}_${cognome}"</code> perché <code>nome_</code> (con underscore finale) sarebbe un nome valido. Con la concatenazione di variabili è preferibile accedere alle variabili con le graffe. | ||
=== Assegnazioni === | === Assegnazioni === | ||
Non si deve usare il <code>'''$'''</code> davanti alla variabile a cui assegnare: | Non si deve usare il <code>'''$'''</code> davanti alla variabile a cui assegnare: | ||
<pre> | <pre> | ||
var=stringa # assegno | var=stringa # assegno una stringa senza spazi e caratteri speciali | ||
var="stringa con spazi" # assegno una stringa con spazi ( | var="stringa con spazi" # assegno una stringa con spazi (e caratteri speciali preceduti da '\') | ||
var='stringa senza apici' # assegno una stringa contenente spazi e caratteri speciali (ma non apici) | var='stringa senza apici' # assegno una stringa contenente spazi e caratteri speciali (ma non apici) | ||
var=$var2 # assegno un'altra variabile | var=$var2 # assegno un'altra variabile | ||
var=${var2} # | var=${var2} # come sopra | ||
var="$var2" # | var="$var2" # come sopra (non serve quotare nelle assegnazioni) | ||
var='$var2' # | var='$var2' # assegno letteralmente $var2 (e non il suo contenuto) | ||
var="\$var2" # come sopra, perché $ è preceduto da \ | var="\$var2" # come sopra, perché $ è preceduto da \ | ||
var="${var1} testo ${var2}_${var3}" # assegno una concatenazione di variabili e stringhe | var="${var1} testo ${var2}_${var3}" # assegno una concatenazione di variabili e stringhe | ||
Riga 160: | Riga 160: | ||
Alcuni caratteri hanno un valore speciale per la shell, per consentirne le espansioni (di variabile, parametro, comando, percorso, ecc...). Di conseguenza se si intende scrivere un carattere speciale senza espanderlo, è necessario comunicarlo alla shell facendolo precedere da un carattere di escape '<code>\</code>' oppure racchiudendolo tra apici o virgolette (a seconda dell'espansione da disattivare). | Alcuni caratteri hanno un valore speciale per la shell, per consentirne le espansioni (di variabile, parametro, comando, percorso, ecc...). Di conseguenza se si intende scrivere un carattere speciale senza espanderlo, è necessario comunicarlo alla shell facendolo precedere da un carattere di escape '<code>\</code>' oppure racchiudendolo tra apici o virgolette (a seconda dell'espansione da disattivare). | ||
Una stringa non racchiusa tra apici o tra virgolette ha i seguenti caratteri speciali: <code>' | Una stringa non racchiusa tra apici o tra virgolette ha i seguenti caratteri speciali: <code>' " ` $ \ { } [ ] * ? ~ ( ) ; & | #</code> | ||
<br/>In determinate circostanze, se non preceduti dal carattere di escape <code>\</code>, possono essere: espansi, eseguiti in background, considerati parte di un nuovo comando o essere tralasciati come commenti. Questa sezione non è esaustiva e non considera tutte le eccezioni, ma consiglia degli accorgimenti che si possono sempre seguire per ridurre la necessità dell'escape. | |||
Inoltre gli spazi ( | Inoltre gli spazi (comprese le tabulazioni) non quotati con apici o virgolette, e non preceduti dal carattere di escape <code>\</code>, vengono compressi. | ||
Per esempio: | Per esempio: | ||
Riga 202: | Riga 203: | ||
===Racchiudere tra apici=== | ===Racchiudere tra apici=== | ||
Con gli apici (apostrofi) si riducono i caratteri speciali a uno soltanto, lo stesso apice, rappresentando la stringa per il suo solo valore letterale e impedendo tutte le espansioni: | Con gli apici (apostrofi) si riducono i caratteri speciali a uno soltanto, lo stesso apice, rappresentando la stringa per il suo solo valore letterale e impedendo tutte le espansioni: | ||
<pre>echo '$PATH "" \ `ls ..` \$HOME ~ * .[a-z]*' # stampa la stringa tra apici, | <pre>echo '$PATH "" \ `ls ..` \$HOME ~ * .[a-z]*' # stampa la stringa tra apici, letteralmente</pre> | ||
Lo svantaggio è che non esiste un carattere di escape: | Lo svantaggio è che non esiste un carattere di escape: | ||
<pre>echo 'L'\''albero di... ' # stampa "L'albero di..." (l'accento non può essere racchiuso tra apici | <pre>echo 'L'\''albero di... ' # stampa "L'albero di..." (l'accento non può essere racchiuso tra apici)</pre> | ||
===Quotare (tra virgolette)=== | ===Quotare (tra virgolette)=== | ||
Racchiudere tra virgolette ogni stringa è raccomandabile, anche se non sempre necessario, così da ridurre | Racchiudere tra virgolette ogni stringa è raccomandabile, anche se non sempre necessario, così da ridurre il numero di caratteri speciali a cui pensare, permettendo allo stesso tempo l'espansione sicura delle variabili e dei comandi. I soli caratteri speciali rimasti sono <code>$</code>, <code>`</code> (ma non l'apice), <code>"</code> e <code>\</code>, che devono essere preceduti dal carattere di escape <code>\</code>. Le sole espansioni permesse all'interno di una stringa quotata sono di variabile/parametro e quelle di comando. | ||
Per esempio: | Per esempio: | ||
Riga 226: | Riga 227: | ||
<pre>`comando`</pre> | <pre>`comando`</pre> | ||
L'output del comando consiste in zero, una o più stringhe | L'output del comando consiste in zero, una o più stringhe: in base agli spazi presenti nell'output prodotto, e in maniera analoga all'espansione a cui sono soggette le variabili. Per trasformare l'output di un comando in una singola stringa è necessario che l'espansione di comando sia quotata, con l'eccezione dell'assegnazione a una variabile. | ||
Esempi di assegnazione: | Esempi di assegnazione: | ||
Riga 240: | Riga 241: | ||
</pre> | </pre> | ||
Passaggio dell'output dei comandi come argomento: | |||
<pre> | <pre> | ||
# stampa stati | # stampa stati | ||
Riga 392: | Riga 393: | ||
</pre> | </pre> | ||
==Concatenazione | ==Concatenazione== | ||
; <code>&&</code> : operatore logico AND, il secondo comando verrà eseguito solo se il primo avrà esito positivo | ; <code>&&</code> : operatore logico AND, il secondo comando verrà eseguito solo se il primo avrà esito positivo | ||
; <code>;</code> : separatore di comandi, il secondo comando verrà eseguito in ogni caso (in uno script è equivalente a un "a capo" e questa è la concatenazione di default) | ; <code>;</code> : separatore di comandi, il secondo comando verrà eseguito in ogni caso (in uno script è equivalente a un "a capo" e questa è la concatenazione di default) | ||
; <code>&</code> : separatore che lancia il comando precedente in background (non c'è exit status e non riceve input da tastiera) | |||
<pre> | |||
cd /percorso/dir && comando | |||
</pre> | |||
Attenzione invece alla '''pericolosità''' di: | |||
<pre> | |||
cd /tmp/tmpdir # cambia la cartella corrente in /tmp/tmpdir | |||
# ma se fallisce, quello successivo verrebbe eseguito comunque! | |||
rm -- ./* # cancella tutti i file nella directory corrente | |||
</pre> | |||
; <code>||</code> : operatore logico OR, il secondo comando è eseguito solo se il primo ha effetto negativo (si può usare anche dopo una sequenza di &&, perché ha priorità inferiore): | |||
; <code>{ ... ; }</code> : esegue un blocco di comandi (dopo l'ultimo servono ";" o un "a capo"). È usata nelle funzioni ed è utile per concatenare && e ||: | |||
<pre> | |||
# interrompe la catena se un comando fallisce | |||
cd /tmp/tmpdir && | |||
rm -- ./* && | |||
rmdir -- /tmp/tmpdir || { | |||
# il blocco è eseguito solo se un comando fallisce | |||
retval=$? | |||
echo "ERRORE (exit status: $retval)" >&2 | |||
exit $retval | |||
} | |||
</pre> | |||
; <code> | ; <code>( ... )</code> : esegue il blocco di comandi in una subshell (le variabili vengono ripristinate al loro valore precedente, alla fine del blocco). | ||
==Redirezione== | |||
Alcune comuni redirezioni: | |||
; <code>| | ; <code>> file</code> scrive l'output sul file (troncandolo, se esiste); | ||
; <code>>> file</code> aggiunge al file (creandolo, se non esiste); | |||
; <code>< file</code> legge l'input dal file; | |||
; <code>>&2</code> scrive l'output sullo standard error; | |||
; <code>2> file</code> scrive lo standard error sul file (per aggiungere: 2>>); | |||
; <code>2>&1</code> scrive lo standard error sullo standard output; | |||
; <code>&> file</code> invia standard output ed error sul file (per aggiungere: &>>); | |||
; <code>comando1 | comando2</code> : pipe che passa l'output del comando1 al comando2 come input. I comandi (anche l'ultimo) sono eseguiti in una subshell. | |||
Esempi: | |||
<pre> | <pre> | ||
comando &> /dev/null # non stampa niente a schermo | |||
comando > /dev/null 2>&1 # equivalente (POSIX) | |||
# filtra le occorrenze di video | |||
dmesg | grep -i video | |||
</pre> | </pre> | ||
===Catturare l'exit status=== | ===Catturare l'exit status=== | ||
Per catturare lo stato d'uscita di un comando appena eseguito è sufficiente espandere la variabile speciale <code>$?</code>, come già visto. Tuttavia in caso di fallimento del comando, il controllo effettuato via <code>$?</code> avverrebbe soltanto '''dopo''' un blocco con errore (si veda la parte sul debug). | Per catturare lo stato d'uscita di un comando appena eseguito è sufficiente espandere la variabile speciale <code>$?</code>, come già visto. Tuttavia in caso di fallimento del comando, il controllo effettuato via <code>$?</code> avverrebbe soltanto '''dopo''' un blocco con errore (si veda la parte sul debug). | ||
Per evitare che un blocco abbia un exit status diverso da zero, si possono usare le concatenazioni (oppure un <code>if</code>): | Per evitare che un blocco abbia un exit status diverso da zero, si possono usare le concatenazioni <code>&&</code> e <code>||</code> (oppure un <code>if</code>): | ||
<pre> | <pre> | ||
comando && | comando && | ||
Riga 446: | Riga 454: | ||
status=$? # se sbagliato | status=$? # se sbagliato | ||
</pre> | </pre> | ||
===Output dei comandi e carattere ASCII n. 0=== | ===Output dei comandi e carattere ASCII n. 0=== | ||
Riga 465: | Riga 467: | ||
</pre> | </pre> | ||
Questo carattere è utile perché nemmeno i file possono averlo nel proprio nome, mentre invece permettono caratteri jolly (*, ?, ...), come già visto con le espansioni di percorso, e potrebbero contenere perfino il carattere "a capo". | |||
L'espansione di percorso funziona normalmente, anche in presenza di "a capo", ma potrebbero sorgere problemi sfruttando l'espansione di comando. Per esempio con il comando esterno <code>find</code>, utilizzato per effettuare ricerche in modo ricorsivo, e che di default restituisce | L'espansione di percorso funziona normalmente, anche in presenza di "a capo", ma potrebbero sorgere problemi sfruttando l'espansione di comando. Per esempio con il comando esterno <code>find</code>, utilizzato per effettuare ricerche in modo ricorsivo, e che di default restituisce i file trovati stampandoli uno per riga, assumendo implicitamente che non contengano il carattere "a capo". | ||
Uno script a titolo esemplificativo: | Uno script a titolo esemplificativo: | ||
Riga 498: | Riga 500: | ||
xargs -0 comando [ argomenti ... ] # li passa come argomenti a un comando esterno | xargs -0 comando [ argomenti ... ] # li passa come argomenti a un comando esterno | ||
</pre> | </pre> | ||
Si leggano i rispettivi manuali per maggiori informazioni. <code>find</code> ha | Si leggano i rispettivi manuali per maggiori informazioni. <code>find</code> ha la possibilità di eseguire altri comandi esterni sui file trovati direttamente con le opzioni -exec ed -execdir, ma la sintassi è più complessa e non supporta più di un processo per volta, come invece <code>xargs</code>. | ||
== Debug integrato == | == Debug integrato == | ||
Riga 509: | Riga 511: | ||
* <code>-x</code> stampa ogni comando prima di eseguirlo; | * <code>-x</code> stampa ogni comando prima di eseguirlo; | ||
* <code>-v</code> stampa l'intero blocco di codice che è stato letto (solo la prima volta); | * <code>-v</code> stampa l'intero blocco di codice che è stato letto (solo la prima volta); | ||
* <code>-u</code> interrompe | * <code>-u</code> interrompe lo script se si accede a una variabile mai assegnata; | ||
* <code>-e</code> interrompe lo script in caso | * <code>-e</code> interrompe lo script in caso di errore (se il comando non è controllato da un <code>if</code>, <code>while</code> o dalla concatenazione con <code>||</code>). | ||
==Link== | ==Link== | ||
* [http://www.gnu.org/software/bash/manual/bash.html Bash Referece Manual]: manuale ufficiale | * [http://www.gnu.org/software/bash/manual/bash.html Bash Referece Manual]: manuale ufficiale | ||
Riga 524: | Riga 523: | ||
|Verificata_da= | |Verificata_da= | ||
:[[Utente:S3v|S3v]] (in Bash tips) | :[[Utente:S3v|S3v]] (in Bash tips) | ||
:[[Utente:HAL 9000|HAL 9000]] | :[[Utente:HAL 9000|HAL 9000]] 18:35, 6 lug 2014 (CEST) | ||
|Estesa_da= | |Estesa_da= | ||
:[[Utente:S3v|S3v]] (in Bash tips) | :[[Utente:S3v|S3v]] (in Bash tips) |
contributi