5.2. Escaping

L'escaping è un metodo per effettuare il quoting di un singolo carattere. Il carattere di escape (\), posto davanti ad un altro carattere, informa la shell che quest'ultimo deve essere interpretato letteralmente.

Attenzione

Con alcuni comandi e utility, come echo e sed, l'escaping di un carattere potrebbe avere un effetto particolare - quello di attribuire un significato specifico a quel carattere (le c.d. sequenze di escape [N.d.T.]).

Significati speciali di alcuni caratteri preceduti da quello di escape:

vengono usati con echo e sed

\n

significa a capo

\r

significa invio

\t

significa tabulazione

\v

significa tabulazione verticale

\b

significa ritorno (backspace)

\a

"significa allerta" (segnale acustico o accensione di un led)

\0xx

trasforma in carattere ASCII il valore ottale 0xx

Esempio 5-2. Sequenze di escape

#!/bin/bash
# escaped.sh: sequenze di escape

echo; echo

# Escaping del ritorno a_capo.
# ------------------

echo ""

echo "Questo messaggio viene visualizzato
su due righe."
# Questo messaggio viene visualizzato
# su due righe.

echo "Questo messaggio viene visualizzato \
su una riga."
# Questo messaggio viene visualizzato su una riga.

echo; echo

echo "============="


echo "\v\v\v\v"      # Visualizza letteralmente: \v\v\v\v .
#  Utilizzate l'opzione  -e  con 'echo' per un corretto impiego delle
#+ sequenze di escape.
echo "============="
echo "TABULAZIONE VERTICALE"
echo -e "\v\v\v\v"   # Esegue 4 tabulazioni verticali.
echo "=============="

echo "VIRGOLETTE"
echo -e "\042"       #  Visualizza " (42 è il valore ottale del 
                     #+ carattere ASCII virgolette).
echo "=============="

# Il costrutto $'\X'  rende l'opzione -e superflua.
echo; echo "A_CAPO E BEEP"
echo $'\n'           # A capo.
echo $'\a'           # Allerta (beep).

echo "==============="
echo "VIRGOLETTE"
# La versione 2 e successive di Bash consente l'utilizzo del costrutto $'\nnn'.
# Notate che in questo caso, '\nnn' è un valore ottale.
echo $'\t \042 \t'   # Virgolette (") tra due tabulazioni.

# Può essere utilizzato anche con valori esadecimali nella forma $'\xhhh'.
echo $'\t \x22 \t'   # Virgolette (") tra due tabulazioni.
# Grazie a Greg Keraunen per la precisazione.
# Versioni precedenti di Bash consentivano '\x022'.
echo "==============="
echo





# Assegnare caratteri ASCII ad una variabile.
# ------------------------------------------
virgolette=$'\042'   # " assegnate alla variabile.
echo "$virgolette Questa è una stringa tra virgolette $virgolette, \
mentre questa parte è al di fuori delle virgolette."

echo

# Concatenare caratteri ASCII in una variabile.

tripla_sottolineatura=$'\137\137\137'  
# 137 è il valore ottale del carattere ASCII  '_'.
echo "$tripla_sottolineatura SOTTOLINEA  $tripla_sottolineatura"

echo

ABC=$'\101\102\103\010'                
# 101, 102, 103 sono i valori ottali di A, B, C.

echo $ABC

echo; echo

escape=$'\033'                         
# 033 è il valore ottale del carattere di escape.

echo "\"escape\" visualizzato come $escape"
# nessun output visibile.

echo; echo

exit 0

Vedi Esempio 34-1 per un'altra dimostrazione di $' ' come costrutto di espansione di stringa.

\"

mantiene il significato letterale dei doppi apici

echo "Ciao"                  # Ciao
echo "\"Ciao\", disse."      # "Ciao", disse.

\$

mantiene il significato letterale del segno del dollaro (la variabile che segue \$ non verrà referenziata)

echo "\$variabile01"  # visualizza $variabile01

\\

mantiene il significato letterale della barra inversa

echo "\\"  # visualizza \

# Mentre . . .

echo "\"   # Invoca il prompt secondario da riga di comando.
           # In uno script provoca un messaggio d'errore.

Nota

Il comportamento della \ dipende dal contesto: se le è stato applicato l'escaping o il quoting, se appare all'interno di una sostituzione di comando o in un here document.

                      #  Escaping e quoting semplice
echo \z               #  z
echo \\z              # \z
echo '\z'             # \z
echo '\\z'            # \\z
echo "\z"             # \z
echo "\\z"            # \z

                      #  Sostituzione di comando
echo `echo \z`        #  z
echo `echo \\z`       #  z
echo `echo \\\z`      # \z
echo `echo \\\\z`     # \z
echo `echo \\\\\\z`   # \z
echo `echo \\\\\\\z`  # \\z
echo `echo "\z"`      # \z
echo `echo "\\z"`     # \z

                      # Here document
cat <<EOF
\z
EOF                   # \z

cat <<EOF              
\\z                     
EOF                   # \z

# Esempi forniti da Stéphane Chazelas.

L'escaping può essere applicato anche ai caratteri di una stringa assegnata ad una variabile, ma non si può assegnare ad una variabile il solo carattere di escape.

variabile=\
echo "$variabile"
# Non funziona - dà un messaggio d'errore:
# test.sh: : command not found
# Un escape "nudo" non può essere assegnato in modo sicuro ad una variabile.
#
#  Quello che avviene effettivamente qui è che la "\" esegue l'escape 
#+ del a capo e l'effetto è         variabile=echo "$variabile"
#+                                  assegnamento di variabile non valido

variabile=\
23skidoo
echo "$variabile"       #  23skidoo
                        #  Funziona, perché nella seconda riga
                        #+ è presente un assegnamento di variabile valido.

variabile=\
#         \^    escape seguito da uno spazio
echo "$variabile"       # spazio

variabile=\\
echo "$variabile"       # \

variabile=\\\
echo "$variabile"
# Non funziona - dà un messaggio d'errore:
# test.sh: \: command not found
#
#  Il primo carattere di escape esegue l'escaping del secondo, mentre il terzo 
#+ viene lasciato "nudo", con l'identico risultato del primo esempio visto 
#+ sopra.

variabile=\\\\
echo "$variabile"       #  \\
                        #  Il secondo ed il quarto sono stati preservati dal
                        #+ primo e dal terzo.
                        #  Questo va bene.

L'escaping dello spazio evita la suddivisione delle parole di un argomento contenente un elenco di comandi.

elenco_file="/bin/cat /bin/gzip /bin/more /usr/bin/less /usr/bin/emacs-20.7"
# Elenco di file come argomento(i) di un comando.

# Aggiunge due file all'elenco, quindi visualizza tutto.
ls -l /usr/X11R6/bin/xsetroot /sbin/dump $elenco_file

echo "-------------------------------------------------------------------------"

# Cosa succede se si effettua l'escaping dei due spazi?
ls -l /usr/X11R6/bin/xsetroot\ /sbin/dump\ $elenco_file
#  Errore: i primi tre file vengono concatenati e considerati come un unico 
#+ argomento per 'ls -l' perché l'escaping dei due spazi impedisce la 
#+ divisione degli argomenti (parole).

Il carattere di escape rappresenta anche un mezzo per scrivere comandi su più righe. Di solito, ogni riga rappresenta un comando differente, ma il carattere di escape posto in fine di riga effettua l'escaping del carattere a capo, in questo modo la sequenza dei comandi continua alla riga successiva.

((cd /source/directory && tar cf - . ) | \ 
(cd /dest/directory && tar xpvf -)
# Ripetizione del comando copia di un albero di directory di Alan Cox,
# ma suddiviso su due righe per aumentarne la leggibilità.

# Come alternativa:
tar cf - -C /source/directory . | 
tar xpvf - -C /dest/directory
# Vedi la nota più sotto.
#(Grazie, Stéphane Chazelas.)

Nota

Se una riga dello script termina con | (pipe) allora la \ (l' escape), non è obbligatorio. È, tuttavia, buona pratica di programmazione utilizzare sempre l'escape alla fine di una riga di codice che continua nella riga successiva.

echo "foo
bar" 
#foo
#bar

echo

echo 'foo
bar'    # Ancora nessuna differenza.
#foo
#bar

echo

echo foo\
bar     # Eseguito l'escaping del carattere a capo.
#foobar

echo

echo "foo\
bar"     #  Stesso risultato, perché \ viene ancora interpretato come escape
         #+ quando è posto tra apici doppi.
#foobar

echo

echo 'foo\
bar'     #  Il carattere di escape \ viene interpretato letteralmente a causa
         #+ del quoting forte.
#foo\
#bar

# Esempi suggeriti da Stéphane Chazelas.