3 581
contributi
m (→Espansione di una variabile: aggiunti esempi) |
(aggiunta espansione di parentesi) |
||
Riga 41: | Riga 41: | ||
=== Espansione di una variabile === | === Espansione di una variabile === | ||
Con l'unica eccezione dell'assegnazione, quando si accede al contenuto di una variabile senza quotarla, questa può essere trasformata in più di una singola stringa ('''esplosione'''), in base agli spazi contenuti, e perfino in "niente" se è vuota ("niente" proprio come se non presente nel codice) | Con l'unica eccezione dell'assegnazione, quando si accede al contenuto di una variabile senza quotarla, questa può essere trasformata in più di una singola stringa ('''esplosione'''), in base agli spazi contenuti, e perfino in "niente" se è vuota ("niente" proprio come se non presente nel codice). | ||
Se si vuole sempre considerare il contenuto della variabile come una singola stringa, è necessario accederla quotata (tra virgolette), ossia con <code>"$variabile"</code> oppure <code>"${variabile}"</code>. Si considerino per esempio i seguenti confronti (usati in genere con <code>if</code>, <code>while</code>, ...): | Entrambi i comportamenti non sono intuitivi e costituiscono una comune sorgente di errori. Se si vuole sempre considerare il contenuto della variabile come una singola stringa, è necessario accederla quotata (tra virgolette), ossia con <code>"$variabile"</code> oppure <code>"${variabile}"</code>. | ||
Si considerino per esempio i seguenti confronti (usati in genere con <code>if</code>, <code>while</code>, ...): | |||
<pre> | <pre> | ||
[ $var = $var2 ] # SBAGLIATO! (se una delle due è vuota) | [ $var = $var2 ] # SBAGLIATO! (se una delle due è vuota) | ||
Riga 173: | Riga 175: | ||
</pre> | </pre> | ||
==Caratteri di escape== | ==Caratteri di escape, apici e virgolette== | ||
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). | ||
Questa sezione non è esaustiva, ma consiglia qualche semplice accorgimento. | Una stringa non racchiusa tra apici ha i seguenti caratteri speciali: <code>'</code>, <code>"</code>, <code>`</code>, <code>$</code>, <code>\</code>, <code>{</code>, <code>[</code>, <code>*</code>, <code>?</code>, <code>~</code>. Se non preceduti dal carattere di escape <code>\</code> possono, in base ai caratteri immediatamente successivi, essere espansi. Questa sezione non è esaustiva, ma consiglia qualche semplice accorgimento, in particolare riguardo l'uso di apici e virgolette per ridurre le necessità dell'escape. | ||
Inoltre gli spazi (comprendendo tabulazioni e a capo) non quotati vengono compressi: | |||
<pre> | |||
echo parola1 parola2 # stampa parola1 parola2 con un singolo spazio | |||
echo "parola1 parola2" # stampa parola1 parola2 mantenendo gli spazi | |||
</pre> | |||
Il carattere di escape <code>\</code> prima di un "a capo", anche se quotato (tra virgolette), ha un significato speciale che consente di scrivere un comando su più righe, trattando ogni riga preceduta da <code>\</code> come la continuazione del comando precedente: | |||
<pre> | |||
# stampa tutto su una riga con un singolo comando echo | |||
echo "testo su \ | |||
più \ | |||
righe, tutto stampato \ | |||
su una singola riga, come scritto \ | |||
tutto di seguito grazie all'uso di \\, \ | |||
ma si noti che \\ dev'essere l'ultimo carattere" | |||
# stampa su più righe (sempre con un singolo comando) | |||
echo "testo su | |||
più | |||
righe, stampato | |||
su più righe, così com'è scritto" | |||
</pre> | |||
===Racchiudere tra apici=== | ===Racchiudere tra apici=== | ||
Riga 200: | Riga 225: | ||
==Espansione di comando== | ==Espansione di comando== | ||
Si effettua racchiudendo un comando tra <code>$( | Si effettua racchiudendo un comando tra <code>$(...)</code>, oppure tra due apici gravi <code>`...`</code> (su tastiera con layout italiano: <code>Alt Gr + '</code>): | ||
<pre>$(comando)</pre> | |||
oppure, meno leggibile e sconsigliata: | |||
<pre>`comando`</pre> | |||
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 206: | Riga 234: | ||
Per esempio: | Per esempio: | ||
<pre> | <pre> | ||
oggi=$(date +%F) # assegna | oggi=$(date +%F) # assegna alla variabile $oggi la data in formato YYYY_MM_DD | ||
# stampa stati | # stampa stati | ||
Riga 248: | Riga 276: | ||
** <code>./*."${estensione}"</code> espande dopo aver espanso la variabile (contrariamente a ~), che può anche essere quotata. | ** <code>./*."${estensione}"</code> espande dopo aver espanso la variabile (contrariamente a ~), che può anche essere quotata. | ||
È importante tenere presente per le espansioni di percorso che, se nessun file combacia con un dato pattern, allora l'espansione | È importante tenere presente per le espansioni di percorso che, se nessun file combacia con un dato pattern, allora l'espansione '''non''' viene effettuata e i caratteri mantengono il loro valore originale. Inoltre <code>*</code> e <code>?</code> sono caratteri validi per un nome di file, e un confronto sull'espansione ottenuta non sarebbe necessariamente risolutivo. | ||
L'esistenza di file ottenuti da tali espansioni va pertanto sempre controllata, per esempio con il costrutto <code>[ -e "$file" ]</code>: | |||
<pre>for file in ./*; do | <pre>for file in ./*; do | ||
Riga 263: | Riga 293: | ||
{{Suggerimento | L'opzione "--" dopo il comando esterno <code>mv</code> serve per comunicargli che le stringhe che seguono non sono opzioni, nemmeno se iniziassero con il carattere "-". È sempre buona norma utilizzarla come controllo aggiuntivo con comandi che accettano file come argomenti, il cui nome non è noto a priori, in particolare per comandi che manipolano i file come: <code>rm</code>, <code>cp</code>, <code>mv</code>, ecc... <br/> | {{Suggerimento | L'opzione "--" dopo il comando esterno <code>mv</code> serve per comunicargli che le stringhe che seguono non sono opzioni, nemmeno se iniziassero con il carattere "-". È sempre buona norma utilizzarla come controllo aggiuntivo con comandi che accettano file come argomenti, il cui nome non è noto a priori, in particolare per comandi che manipolano i file come: <code>rm</code>, <code>cp</code>, <code>mv</code>, ecc... <br/> | ||
L'opzione deve essere supportata dal comando esterno, non è trattata specialmente dalla shell.}} | L'opzione deve essere supportata dal comando esterno, non è trattata specialmente dalla shell.}} | ||
==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>, in determinate circostanze possono essere espansi. | |||
L'espansione supporta due forme: una iterativa, da espandere in un intervallo da un indice a un altro, e una dichiarativa, da espandere nei valori della lista fornita. La prima espansione sostituisce spesso la necessità di ricorrere al comando esterno <code>seq</code>, utilizzato da <code>'''sh'''</code> (''POSIX''). | |||
Sintassi della forma iterativa (con indici di un intervallo): | |||
<code>prefisso{x..y[..z]}suffisso</code> espande iterativamente a tutte le stringhe a partire da "prefisso'''x'''suffisso" fino a "prefisso'''y'''suffisso", con incrementi di 1 (o '''z''' se specificato). Le stringhe prefisso e suffisso possono essere omesse, e anche essere variabili (anche quotate, purché le graffe non lo siano), mentre x, y e z devono essere determinati valori: | |||
* <code>{x..y}</code> dove x e y sono due interi (non possono essere variabili); | |||
* <code>{x..y..z}</code> dove x, y e z sono tre interi (non possono essere variabili); | |||
* <code>{a..b}</code> dove a e b sono due caratteri (non possono essere variabili); | |||
* <code>{a..b..z}</code> dove a e b sono due caratteri, e z è un intero (non possono essere variabili). | |||
Per esempio: | |||
<pre> | |||
# crea un file temporaneo, associa il percorso a $tmp_file | |||
tmp_file=$(tempfile) | |||
# crea altri dieci file temporanei (.0, .1, .., .9) con lo stesso nome | |||
touch -- "$tmp_file".{0..9} | |||
# operazioni varie con i file | |||
# ... | |||
# pulizia prima di terminare lo script | |||
rm -- "$tmp_file" "$tmp_file".{0..9} | |||
</pre> | |||
Sintassi della forma dichiarativa (lista di stringhe): | |||
<code>prefisso{stringa1,stringa2,...}suffisso</code> espande a tutte le stringhe nella lista, racchiudendole tra il prefisso e il suffisso dati, se presenti. Il prefisso, il suffisso e tutte le stringhe possono essere variabili, anche quotate, purché non siano quotate le graffe e le virgole interne. | |||
Questa espansione è effettuata prima di tutte le altre, e il risultato dell'espansione se non quotato può quindi subire ulteriori espansioni. Per esempio per effettuare un'operazione sui file nella cartella corrente che hanno una data estensione, si può scrivere: | |||
<pre> | |||
for file in ./*.{odt,abw,txt,rtf,doc}; do | |||
if [ -e "$file" ]; then | |||
... | |||
fi | |||
done | |||
</pre> | |||
che è equivalente a: | |||
<pre> | |||
for file in ./*.odt ./*.abw ./*.txt ./*.rtf ./*.doc; do | |||
if [ -e "$file" ]; then | |||
... | |||
fi | |||
done | |||
</pre> | |||
==Concatenazione e redirezione== | ==Concatenazione e redirezione== | ||
Riga 338: | Riga 415: | ||
|Verificata_da= | |Verificata_da= | ||
:[[Utente:S3v|S3v]] (versione in Bash tips) | :[[Utente:S3v|S3v]] (versione in Bash tips) | ||
:[[Utente:HAL 9000|HAL 9000]] | :[[Utente:HAL 9000|HAL 9000]] 14:28, 4 lug 2014 (CEST) | ||
|Estesa_da= | |Estesa_da= | ||
:[[Utente:S3v|S3v]] (versione in Bash tips) | :[[Utente:S3v|S3v]] (versione in Bash tips) |
contributi