DanLevy.net

Quiz: Padronanza di Bash e Shell

Riesci a parlare con i computer? Tipo, bene?

Metti alla prova le tue competenze di scripting Bash con queste 16 domande!

Copre variabili, cicli, condizioni, manipolazione di stringhe, funzioni e le insidie della sintassi, dalle più semplici alle più subdole.

Affina (o dimostra) le tue competenze di scripting shell!

Come si definiscono le variabili in Bash?

Le variabili in Bash si dichiarano senza spazi intorno al segno =. Per esempio:

Terminal window
name=Alice

Questo assegna il valore "Alice" alla variabile name.

Nota: $name è usato per riferire o leggere il valore di una variabile.

Aggiungere spazi fa sì che la shell interpreti il comando come un programma da eseguire, il che non è quello che vuoi quando imposti una variabile.

Inoltre, Bash è sensibile al maiuscolo/minuscolo, quindi name, NAME e Name sono variabili diverse.

Infine, le variabili non possono contenere spazi o trattini (-) nei loro nomi. Usa underscore (_) o camelCase invece.

Cosa stamperà It's 🔨 Time!?

Lo so. È pazzesco quanto rapidamente l’escaping renda le stringhe difficili da analizzare. Immagina di fare l’escaping di altri linguaggi nelle stringhe Bash – con tutte quelle virgolette, apostrofi e simboli $ pronti a farti impazzire. 🫠

Le virgolette singole devono essere escapeate all’interno di stringhe delimitate da virgolette singole. La sequenza chiudi-virgoletta, escape-virgoletta, riapri-virgoletta ('\'') permette di stampare:

It's 🔨 Time!

Ci sono altri modi per gestirlo, ma questo è il più comune.

Quale sarà l’output di questo comando?

Terminal window
echo c{a,b}t

Le espansioni con parentesi graffe {} generano più versioni del contesto della stringa, una (o più) per ogni valore separato da virgola o modello.

Qui, c{a,b}t si espande in:

cat cbt

Ora, cosa stamperà?

Terminal window
price="$100"
echo "Cost: $price"

Le variabili numerate hanno un significato speciale. In questo caso, $1 è una variabile speciale che contiene il primo argomento passato allo script o alla funzione.

Poiché stiamo eseguendo lo script in una REPL, non ci sono argomenti, quindi $1 è vuota. Il testo rimanente 00 viene stampato così com’è.

Per stampare un carattere $ letterale, usa gli apici singoli o escapalalo con una barra rovesciata (\):

Terminal window
price="\$100"
echo "Cost: $price"

Cosa sta succedendo qui?

Terminal window
str="Bark bark"
echo ${str/bark/meow}

La sintassi ${var/pattern/replacement} sostituisce la prima occorrenza di pattern con replacement. Qui, l’output è:

Bark meow

È sensibile al maiuscolo/minuscolo. Per gestire sia bark che Bark, usa un pattern come ${var/[Bb]ark/Bark} o normalizza la stringa prima della sostituzione.

Per sostituire tutte le occorrenze, usa ${var//pattern/replacement}.

Per sostituire dall’inizio della stringa, usa ${var/#pattern/replacement}.

Per sostituire dalla fine della stringa, usa ${var/%pattern/replacement}.

Come puoi ottenere la lunghezza di una variabile in Bash?

La sintassi ${#username} restituisce la lunghezza di username.

Per esempio:

Terminal window
username="@justsml"
echo ${#username} # => 8

Mentre wc funzionerebbe, tecnicamente non fa parte di Bash.

L’utilità wc è una vecchia battuta interna che si riferisce a “water closet”, ovvero il bagno. SCHERZO! Qualcuno legge queste cose?

In realtà wc è un comando antico di POSIX (e dei giorni AT&T Unix). È l’abbreviazione di “word count” e può contare linee, parole e caratteri in un file o flusso di input.

Cosa stampa questo script se il file cats.txt ESISTE?

Terminal window
if [ -e cats.txt]; then
echo "File exists"
else
echo "File does not exist"
fi

Hai notato lo spazio mancante prima della parentesi di chiusura?

Bash è piuttosto esigente qui: gli spazi sono obbligatori dentro le espressioni tra parentesi.

Poiché lo spazio mancante fa sì che il comando [ non veda la parentesi ] di chiusura, Bash stampa una diagnostica, considera il test fallito e passa al ramo else.

La sintassi corretta è:

Terminal window
if [ -e example.txt ]; then
echo "File exists"
else
echo "File does not exist"
fi

Nota: le doppie parentesi quadre [[ ]] sono raccomandate per le espressioni condizionali. Vedi BashFAQ.

Come possiamo confrontare le stringhe in Bash?

Terminal window
cat1="Rosie"
cat2="Sunflower"
if [ "$cat1" === "$cat2" ]; then
echo "Same cat"
else
echo "Different cats"
fi

Un altro errore di sintassi di test!

Hai notato l’operatore === non valido?

Potresti aver pensato a JavaScript…

Con [ ... ], Bash segnala una diagnostica e la condizione è falsa, quindi il ramo else stampa Different cats. In Bash, usa = o == per i confronti di uguaglianza.

Cosa stamperà questo script?

Terminal window
function greet () {
echo "$1"
}
greet Hi Dan

Le funzioni in Bash possono accettare argomenti. La variabile $1 contiene il primo argomento passato alla funzione.

Ricorda, $0 è il nome dello script, $1 è il primo argomento, $2 è il secondo, e così via. Gli spazi separano gli argomenti. Quindi, greet Hi Dan passa "Hi" come primo argomento. Per passare "Hi Dan" come unico argomento, devi racchiuderlo tra virgolette: greet "Hi Dan".

Quale operatore collega l’output di un comando all’input del comando successivo?

L’operatore pipe | collega l’output di un comando all’input di un altro. Per esempio:

Terminal window
echo "Mr. Levy 👨🏻‍🔬" | wc -m
# => 14

Come funziona la matematica in Bash?

La sintassi (( )) esegue operazioni aritmetiche intere in Bash.

Può essere usata per calcoli semplici:

Terminal window
((result = 2 + 2))
echo $result # => 4

Oppure per espressioni condizionali:

Terminal window
if (( 2 > 1 )); then
echo "2 is greater than 1"
fi

Per l’aritmetica a virgola mobile, considera l’uso di bc o awk.

Quale di questi moltiplica correttamente 10 e 0.5, stampando 5?

La sintassi (( )) esegue SOLO aritmetica intera. Sai, numeri interi, senza virgola mobile!

Bash (forse sorprendentemente) non ha supporto integrato per l’aritmetica a virgola mobile.

La soluzione più comune è usare gli utilità GNU bc o awk.

Cosa fa il : in questo script?

Terminal window
rosie="Bad cat, good cat"
echo ${rosie:9}

La sintassi ${var:offset} estrae una sottostringa a partire da offset. Qui, l’output è:

good cat

Per estrarre una sottostringa di lunghezza specifica, usa ${var:offset:length}.

Per estrarre dalla fine della stringa, usa ${var: -offset}. (Nota lo spazio prima del -!)

Quale NON è una parola chiave per i cicli in Bash?

each non è una parola chiave di loop in Bash. Le principali parole chiave di loop sono for, while e until.

Sebbene do non sia tecnicamente una parola chiave di loop, è una parte fondamentale della sintassi del loop.

Quale opzione eseguirà il comando ls -l e restituirà l’output?

La sintassi $(ls -l) esegue il comando all’interno delle parentesi e sostituisce l’output. Per esempio:

Terminal window
echo "Today is $(date +%F)"
# => Today is 2029-12-31

La prima opzione utilizza gli apici singoli ', non i backtick. Questo impedisce l’espansione, quindi '$(date +%F)' stamperebbe semplicemente la stringa letterale $(date +%F).

Sebbene sia ancora supportato usare i backtick (`ls -l`) per l’esecuzione di comandi, recentemente è diventato un po’ un anti-pattern (in alcuni contesti). La maggior parte raccomanda di usare $(command) per una migliore leggibilità e coerenza con diverse shell e versioni.

Le parentesi graffe ${} sono usate per l’espansione di variabili, non per la sostituzione di comandi.

Il carattere % non è usato per la sostituzione di comandi.

Quale operatore viene usato per combinare l’output di errore nell’output standard?

L’operatore 2>&1 reindirizza lo standard error (descrittore file 2) allo standard output (descrittore file 1). Questo è utile per catturare i messaggi di errore nello stesso flusso di output del normale output.

L’operatore 1>&2 reindirizza lo standard output allo standard error, tuttavia la domanda chiedeva come reindirizzare lo standard error allo standard output.

Per saperne di più su cosa succede dietro le quinte, consulta l’eccellente FAQ di Redirection di Greg.

Inoltre, grazie all’utente Reddit u/OneTurnMore per i suggerimenti di copia.

Il mio Quiz su Bash ti ha lasciato a pezzi?

Fammi sapere nei commenti qui sotto!

Ulteriori letture

Rafforza le tue competenze Bash con le seguenti risorse: