Qual è l'utilità del comando: nello script di shell, dato che non fa esplicitamente nulla?


27

Nella risposta a questa domanda sui commenti negli script di shell , è indicato che :è un comando null che non fa esplicitamente nulla (ma non deve essere usato per i commenti).

Quale sarebbe l'utilità di un comando che non fa assolutamente nulla?



2
Vedi anche questa domanda che ha una risposta ancora migliore qui , vale a dire che :è necessario essere un built-in, mentre truenon lo è, che influenza l'ambito delle variabili
Old Pro

2
Non fa esplicitamente nulla con grazia .
Mikeserv,

Risposte:


19

Di solito uso truenei loop; Penso che sia più chiaro:

while true; do
    ...
done

L'unico posto che ho trovato :davvero utile è nelle dichiarazioni dei casi, se devi abbinare qualcosa ma non vuoi davvero fare nulla. Per esempio:

case $answer in
    ([Yy]*) : ok ;;
    (*)     echo "stop."; exit 1 ;;
esac

3
Sono d'accordo. trueper una condizione, :per un NOP.
jw013,

1
bash accetta case a in a ) ;; esac. Ci sono delle conchiglie che non lo accettano?
Kaz,

@Kaz: secondo la grammatica della shell POSIX , case ${var} in value);; *) do_something;; esacè accettabile. Il :comando non è necessario per casi vuoti.
Richard Hansen,

12

Inizialmente, veniva utilizzato per determinare che si trattava di un programma shell Bourne, al contrario del programma compilato C. Questo prima che Shebang e più linguaggi di scripting (csh, perl). Puoi comunque eseguire uno script a partire solo da ::

$ echo : > /tmp/xyzzy
$ chmod +x /tmp/xyzzy
$ ./xyzzy

Generalmente eseguirà lo script contro $SHELL(o /bin/sh).

Da allora, l'uso principale è valutare gli argomenti. Uso ancora:

: ${EDITOR:=vim}

per impostare un valore predefinito in uno script.


11

: è utile per scrivere loop che devono essere terminati dall'interno.

while :
do
    ...stuff...
done

Questo funzionerà per sempre a meno breakche non exitvenga chiamato, o la shell non riceva un segnale di chiusura.


3
Sento che while true; do ...; donecomunica le intenzioni al lettore meglio diwhile :; do ...; done
Richard Hansen,

9

Quando si desidera un'istruzione "Maybe" negli script di shell, o si utilizza una condizione "non", che può apparire sciocca per alcuni dei test, oppure si utilizza ':' nella clausola true, con codice reale nel falso- clausola.

if [ some-exotic-condition ]
then
    :
else
    # Real code here
fi

La "condizione esotica" potrebbe essere qualcosa che non vuoi negare, o è molto più chiaro se non usi la "logica negativa".


1
Viene inoltre visualizzato negli script generati da autoconfperché è molto più semplice aggiungere un valore predefinito :per i rami vuoti piuttosto che capire come invertire la condizione.
Dietrich Epp,

2
Non riesco a vedere quanto sia ficcanaso !davanti a un [ some-exotic-condition ]goffo, ma un superfluo : elsedopo non è sciocco.
Kaz,

@Kaz ha un buon punto. Ricordiamo che inventare condizioni esotiche è nella migliore delle ipotesi difficile. Se devi negare tutto, questa è una cosa, ma potrebbe solo rendere meno chiara la condizione. Fa un "!" negare l'intera condizione o solo il primo termine? Meglio avere una clausola ':' vera a volte.
Bruce Ediger,

Il !token annulla un intero elemento della pipe di comando. while ! grep ... ; do ... done oppure if ! [ ... ] ; then ... fi. È sostanzialmente esterno alla test/[]sintassi. Vedi: pubs.opengroup.org/onlinepubs/9699919799/utilities/…
Kaz

5

L'ho usato solo in aggiunta al carattere # per commentare temporaneamente una riga, in una situazione in cui commentare la riga produce un errore di sintassi, a causa di un difetto nella grammatica della shell di non consentire una sequenza vuota di comandi :

if condition ; then
    :# temporarily commented out command
fi

Senza: abbiamo una sequenza di comandi mancante, che è un errore di sintassi.


4

Ci sono due casi in cui trovo :utile:

Assegnazioni di variabili predefinite

#!/bin/sh

# set VAR to "default value" if not already set in the environment
: "${VAR=default value}"

# print the value of the VAR variable.  Note that POSIX says the behavior
# of echo is implementation defined if the first argument is '-n' or if any
# argument contains a '\', so use printf instead of echo.
printf '%s\n' "VAR=${VAR}"

Questo è un modo conveniente per consentire agli utenti dello script della shell di sovrascrivere un'impostazione senza modificare lo script. (Tuttavia, gli argomenti della riga di comando sono migliori perché non si corre il rischio di comportamenti imprevisti se l'utente ha casualmente la variabile utilizzata nel proprio ambiente esportato.) Ecco come l'utente sovrascriverà l'impostazione:

VAR="other value" ./script

La ${VAR=value}sintassi dice di impostare VARsu valuese VARnon è già impostato, quindi espandere il valore della variabile. Dato che non ci interessa ancora il valore della variabile, viene passato come argomento al comando no-op :per eliminarlo.

Anche se :è un comando no-op, l'espansione viene eseguita dalla shell (non dal :comando!) Prima di eseguire il :comando in modo che l'assegnazione della variabile si verifichi comunque (se applicabile).

Sarebbe anche accettabile usare trueo qualche altro comando invece di :, ma il codice diventa più difficile da leggere perché l'intenzione è meno chiara.

Anche il seguente script funzionerebbe:

#!/bin/sh

# print the value of the VAR variable.  Note that POSIX says the behavior
# of echo is implementation defined if the first argument is '-n' or if any
# argument contains a '\', so use printf instead of echo.
printf '%s\n' "VAR=${VAR=default value}"

Ma quanto sopra è molto più difficile da mantenere. Se ${VAR}viene aggiunta una riga che utilizza sopra quella printfriga, è necessario spostare l'espansione dell'assegnazione predefinita. Se lo sviluppatore dimentica di spostare quell'assegnazione, viene introdotto un bug.

Qualcosa da mettere in un blocco condizionale vuoto

I blocchi condizionali vuoti dovrebbero generalmente essere evitati, ma a volte sono utili:

if some_condition; then
    # todo:  implement this block of code; for now do nothing.
    # the colon below is a no-op to prevent syntax errors
    :
fi

Alcune persone sostengono che avere un ifblocco vero vuoto può rendere il codice più facile da leggere che negare il test. Per esempio:

if [ -f foo ] && bar || baz; then
    :
else
    do_something_here
fi

è probabilmente più facile da leggere di:

if ! [ -f foo ] || ! bar && ! baz; then
    do_something_here
fi

Tuttavia credo che ci siano alcuni approcci alternativi che sono migliori di un blocco vero vuoto:

  1. Metti la condizione in una funzione:

    exotic_condition() { [ -f foo ] && bar || baz; }
    
    if ! exotic_condition; then
        do_something_here
    fi
    
  2. Inserisci la condizione tra parentesi graffe (o parentesi, ma le parentesi generano un processo subshell e tutte le modifiche apportate all'ambiente all'interno della subshell non saranno visibili all'esterno della subshell) prima di annullare:

    if ! { [ -f foo ] && bar || baz; } then
        do_something_here
    fi
    
  3. Usa ||invece di if:

    [ -f foo ] && bar || baz || {
        do_something_here
    }
    

    Preferisco questo approccio quando la reazione è una semplice linea, come affermare le condizioni:

    log() { printf '%s\n' "$*"; }
    error() { log "ERROR: $*" >&2; }
    fatal() { error "$@"; exit 1; }
    
    [ -f foo ] && bar || baz || fatal "condition not met"
    

1

Nella vecchia shell pre-bourne nelle versioni antiche di UNIX, il :comando era originariamente destinato a specificare le etichette per goto(era un comando separato che avvolge l'input nel punto in cui si trova l'etichetta, quindi le etichette non potrebbero essere una sintassi separata che il shell sa che ifera anche un comando separato.) Presto venne usato per i commenti, prima che ci fosse una sintassi dei commenti ( #era usata per il backspace) e oggigiorno è in circolazione per la compatibilità più o meno.


0

Oltre a usarlo come un'istruzione che non fa nulla, è possibile utilizzarlo per commentare singole istruzioni trasformandole in argomenti per:.


Non sarà esattamente un commento poiché : echo write this line > myfilecreerà comunque un file vuoto.
Arcege,

5
Come spiegato nel link nella domanda, NON: è un meccanismo di commento adeguato.
jw013,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.