3 581
contributi
(espansione aritmetica intera) |
(correzioni, riordinamento, aggiunte priorità delle espansioni) |
||
Riga 1: | Riga 1: | ||
{{Versioni_compatibili}} | {{Versioni_compatibili}} | ||
==Introduzione== | ==Introduzione== | ||
Questa non è una guida completa, per la vastità dell'argomento, ma cercherà di far luce sui comportamenti più distintivi di Bash, | Questa non è una guida completa, per la vastità dell'argomento, ma cercherà di far luce sui comportamenti più distintivi di Bash, con enfasi particolare sulle espansioni di stringhe. | ||
Per l'uso interattivo si rimanda a [[Bash tips]]. | Per l'uso interattivo si rimanda a [[Bash tips]]. | ||
Riga 42: | Riga 42: | ||
Ciò è ancora più importante quando si passa la variabile a un comando che agisce su un file indicato dalla variabile, il cui contenuto in presenza di spazi (comuni per i nomi di file degli utenti) potrebbe venir trattato come una lista di file. | Ciò è ancora più importante quando si passa la variabile a un comando che agisce su un file indicato dalla variabile, il cui contenuto in presenza di spazi (comuni per i nomi di file degli utenti) potrebbe venir trattato come una lista di file. | ||
Esempio di codice che crea un backup di un file indicato da una variabile | Esempio di codice che crea un backup di un file indicato da una variabile: | ||
<pre> | <pre> | ||
cp -- "$file" "${file}.bak" | |||
</pre> | </pre> | ||
Riga 91: | Riga 87: | ||
wait $pid # attendo la terminazione del comando | wait $pid # attendo la terminazione del comando | ||
status=$? # catturo il suo exit status | status=$? # catturo il suo exit status | ||
</pre> | </pre> | ||
Riga 207: | Riga 141: | ||
===Quotare (tra virgolette)=== | ===Quotare (tra virgolette)=== | ||
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 quelle di variabile/parametro | 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 quelle attivate da <code>$</code>, ossia di variabile/parametro, di comando e aritmetiche. | ||
Per esempio: | Per esempio: | ||
Riga 218: | Riga 152: | ||
echo "~ * .[a-z]*" # non effettua le espansioni di tilda e percorso, ma stampa letteralmente | echo "~ * .[a-z]*" # non effettua le espansioni di tilda e percorso, ma stampa letteralmente | ||
echo "{a,b} $'\n'" # stampa letteralmente, senza espansioni | echo "{a,b} $'\n'" # stampa letteralmente, senza espansioni | ||
</pre> | |||
Le espansione attivate da <code>$</code> avvengono con la stessa priorità, e in una stringa quotata sono le uniche permesse, quindi il risultato di un'espansione non può essere espanso una seconda volta all'interno di una stringa quotata. | |||
==Espansione di parametro (stringa)== | |||
È una forma modificata dell'espansione di variabile, che permette di operare sulla stringa contenuta con un modificatore. | |||
L'espansione di parametro è utilizzabile ogni volta che lo è quella di variabile, con un'unica differenza: l'espansione di variabile ha priorità maggiore, il che permette di inserire una stringa ottenuta dall'espansione di una variabile in un'espansione di parametro, mentre non è possibile annidare più espansioni di parametro. | |||
Modificatori: | |||
* <code>${#var}</code> ritorna il numero di caratteri della stringa contenuta in $var; | |||
* <code>${!var}</code> ritorna il contenuto della variabile, il cui nome è contenuto in $var (accesso indiretto); | |||
* espande o assegna valori di default/alternativi; | |||
* manipolatori di stringa (rimozione e sostituzione); | |||
* trasformazione in uppercase / lowercase. | |||
===Manipolazione delle stringhe=== | |||
Nelle shell *nix, storicamente, la manipolazione delle stringhe viene fatto attraverso programmi esterni alla shell come sed, awk e perl. Questi programmi vengono ancora usati quando si vuole mantenere la compatibilità con la shell <code>'''sh'''</code> (''POSIX'') o per manipolazioni molto complesse. | |||
Se si usa Bash non è necessario usare nessun programma esterno, ma basta imparare i tre operatori fondamentali ed alcuni concetti di base, per poter fare tutte le manipolazioni più comuni direttamente sulle variabili. | |||
Si assegna una stringa a una variabile e accedendola tramite la forma con le graffe, si può ricorrere a un modificatore che manipola la stringa (senza modificare il contenuto della variabile), ad esempio: | |||
<pre> | |||
VAR="stringa-di-esempio" | |||
echo "${VAR#stringa-}" | |||
</pre> | |||
ritorna il contenuto della variable VAR senza il prefisso "stringa-". VAR non viene modificata, salvo una nuova assegnazione: | |||
<pre> | |||
VAR=${VAR#stringa-} | |||
</pre> | |||
ora il prefisso "stringa-" è stato eliminato anche dalla variabile VAR. | |||
I modificatori sono molti, ma possono essere facilmente ricordati se si imparano i tre fondamentali: | |||
* <code>#</code> sottrae dall'inizio della stringa ''(minimale)''; | |||
* <code>%</code> sottrae dalla fine della stringa ''(minimale)''; | |||
* <code>/</code> sostituisce una sottostringa con un'altra ''(solo la prima volta che viene incontrata)''. | |||
Questi operatori sono minimali, questo vuol dire che se si usano le espressioni regolari per indicare la sottostringa (da eliminare o sostituire) verrà individuata in caso di ambiguità la sottostringa più piccola (o solo la prima nel caso della sostituzione). | |||
Per ottenere gli operatori massimali basta raddoppiare il simbolo: | |||
* <code>##</code> sottrae dall'inizio della stringa ''(massimale)''; | |||
* <code>%%</code> sottrae dalla fine della stringa ''(massimale)''; | |||
* <code>//</code> sostituisce una sottostringa con un'altra ''(tutte le volte che viene incontrata)''. | |||
Gli operatori massimali cercano di individuare la sottostringa più grande che corrisponde all'espressione regolare (nel caso del modificatore '''//''' tutte le sottostringhe vengono sostituite). | |||
Si noti che le stringhe interne a un'espansione di parametro possono essere delle variabili, ma non altre espansioni di parametro: | |||
<pre> | |||
# cambia l'estensione nella variabile file | |||
if [ "$file" != "${file%${estensione}}" ]; then | |||
file=${file%${estensione}}${nuova_estensione} | |||
fi | |||
</pre> | |||
Per una spiegazione dettagliata di tutti i modificatori e anche di altri modi di manipolare le stringhe in Bash (ad esempio <code>expr</code>) vedere: | |||
* [http://www.tldp.org/LDP/abs/html/string-manipulation.html Advanced Bash-Scripting Guide: Manipulating Strings] | |||
====Esempi: manipolazione delle stringhe==== | |||
<pre> | |||
VAR="questa.sarebbe.una.stringa.di.esempio" | |||
# Risultato: | |||
echo "${VAR#*.}" # --> sarebbe.una.stringa.di.esempio | |||
echo "${VAR##*.}" # --> esempio | |||
echo "${VAR%.*}" # --> questa.sarebbe.una.stringa.di | |||
echo "${VAR%%.*}" # --> questa | |||
echo "${VAR/st/ST}" # --> queSTa.sarebbe.una.stringa.di.esempio | |||
echo "${VAR//st/ST}" # --> queSTa.sarebbe.una.STringa.di.esempio | |||
</pre> | |||
====Esempio: alternativa a basename==== | |||
Quando in uno script ci si deve riferire al nome dello script stesso, è usuale utilizzare il comando esterno <code>'''basename'''</code>. Una possibile alternativa: | |||
<pre> | |||
usage () { | |||
echo "Usage: ${0##*/}" | |||
} | |||
</pre> | </pre> | ||
==Espansione di comando== | ==Espansione di comando== | ||
Consiste nel trasformare l'output di un comando qualsiasi (interno della shell, esterno, una funzione e anche forme composte) in argomenti per un altro comando, oppure nel valore da assegnare a una variabile. Si effettua racchiudendo un comando tra <code>$(...)</code> | Consiste nel trasformare l'output di un comando qualsiasi (interno della shell, esterno, una funzione e anche forme composte) in argomenti per un altro comando, oppure nel valore da assegnare a una variabile. Si effettua racchiudendo un comando tra <code>$(...)</code>: | ||
<pre>$(comando)</pre> | <pre>$(comando)</pre> | ||
oppure, meno leggibile e sconsigliata: | oppure, meno leggibile e sconsigliata tra <code>`...`</code> (su tastiera con layout italiano: <code>Alt Gr + '</code>): | ||
<pre>`comando`</pre> | <pre>`comando`</pre> | ||
Inoltre la prima forma può essere annidata facilmente, mentre la seconda richiederebbe un livello aggiuntivo di escape. | |||
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. | 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. | ||
Riga 305: | Riga 320: | ||
==Espansione di tilda== | ==Espansione di tilda== | ||
Sintassi: | Sintassi: | ||
* <code>~</code> | * <code>~</code> si espande alla home, se non è quotata (equivalente all'uso di $HOME, che può essere quotata); | ||
* <code>~utente</code> si espande alla home di un dato utente, se esiste, ma la stringa non può essere quotata né essere una variabile. | * <code>~utente</code> si espande alla home di un dato utente, se esiste, ma la stringa non può essere quotata né essere una variabile. | ||
Si distingue dall'espansione di percorso perché: | |||
* può essere espansa in un'assegnazione, se non è quotata; | |||
* ha priorità maggiore dell'espansione di parametro/variabile; per cui, se assegnata quotata a una variabile, non sarà espansa quando si accede alla variabile. | |||
Esempi: | Esempi: | ||
<pre> | <pre> | ||
var=~ | var=~ # assegno la home dell'utente a $var | ||
var=$HOME # equivalente (ma più chiaro) | |||
var="~" # assegno ~ a $var | |||
var= | echo "$var" # stampo ~ | ||
var | echo $var # equivalente (nessuna espansione) | ||
var= | var=~root # assegno a var la home di root | ||
echo ~ | echo ~ # stampo la home dell'utente | ||
echo "~" | echo "$HOME" # equivalente | ||
echo ~root | echo "~" # stampo ~ | ||
echo ~fdsfd | echo ~root # stampo la home di root | ||
echo ~fdsfd # stampo ~fdsfd (l'utente fdsfd non esiste) | |||
</pre> | </pre> | ||
Riga 325: | Riga 345: | ||
{{Box | File | Su UNIX e Unix-like per file si può intendere sia un file regolare, ma anche una directory, un link simbolico, una pipe, un socket, un device, ecc...}} | {{Box | File | Su UNIX e Unix-like per file si può intendere sia un file regolare, ma anche una directory, un link simbolico, una pipe, un socket, un device, ecc...}} | ||
Le espansioni di percorso sono possibili solo se i caratteri speciali che la consentono non sono racchiusi tra virgolette, apici o preceduti da <code>/<code>. È sempre consigliabile racchiudere tutto il resto tra virgolette, per non permettere espansioni accidentali. | |||
L'espansione non è possibile, direttamente, in un'assegnazione. Avendo la priorità più bassa, contrariamente all'espansione di tilda può avvenire anche in seguito all'espansione di una variabile (e con ogni altra espansione), se non è quotata: | |||
<pre> | <pre> | ||
var=* | var="./*" # assegno ./* a $var | ||
var= | var=./* # come sopra (nessuna espansione in un'assegnazione) | ||
echo "$var" # stampa letteralmente * | echo "$var" # stampa letteralmente ./* | ||
echo $var # stampa la lista di tutti i file non nascosti | echo $var # stampa la lista di tutti i file non nascosti | ||
# nella directory corrente, oppure * se è vuota | # nella directory corrente, oppure ./* se è vuota | ||
</pre> | </pre> | ||
Riga 348: | Riga 368: | ||
* <code>"./${nome}"*</code>espande a tutti i file inizianti con $nome; | * <code>"./${nome}"*</code>espande a tutti i file inizianti con $nome; | ||
* <code>./*/</code> espande a tutte le directory non nascoste; | * <code>./*/</code> espande a tutte le directory non nascoste; | ||
* <code>./.*</code> espande a tutti i file nascosti (comprese "'''.'''" e "'''..'''", ossia directory corrente e superiore). | * <code>./.*</code> espande a tutti i file nascosti ('''ATTENZIONE:''' comprese "'''.'''" e "'''..'''", ossia directory corrente e superiore). | ||
È importante sapere che, se nessun file combacia con un dato pattern, allora l'espansione '''non''' viene effettuata e i caratteri mantengono il loro valore letterale. E inoltre <code>*</code> e <code>?</code> sono caratteri validi per un nome di file. | È importante sapere che, se nessun file combacia con un dato pattern, allora l'espansione '''non''' viene effettuata e i caratteri mantengono il loro valore letterale. E inoltre <code>*</code> e <code>?</code> sono caratteri validi per un nome di file. | ||
Riga 385: | Riga 405: | ||
==Espansione di parentesi (graffa)== | ==Espansione di parentesi (graffa)== | ||
Se i caratteri <code>{</code> e <code>}</code> non sono quotati, e non sono preceduti dal carattere di escape <code>\</code>, possono essere espansi con due diverse sintassi. | Se i caratteri <code>{</code> e <code>}</code> non sono quotati, e non sono preceduti dal carattere di escape <code>\</code>, possono essere espansi con due diverse sintassi per generare una lista di stringhe. E più espansioni di parentesi possono essere annidate. | ||
Questa espansione avviene prima di tutte le altre, e il risultato può passare per tutte le altre espansioni. Non può avvenire in un'assegnazione, se non all'interno di altre espansioni. | |||
===Con indici di intervallo=== | ===Con indici di intervallo=== | ||
Riga 555: | Riga 577: | ||
|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]] 12:05, 12 lug 2014 (CEST) | ||
|Estesa_da= | |Estesa_da= | ||
:[[Utente:S3v|S3v]] (in Bash tips) | :[[Utente:S3v|S3v]] (in Bash tips) |
contributi