Qual è il punto dell'operatore Null bash “:”, due punti?


13

Qual è il punto dell'operatore "null" in uno script BASH? Comprendo che viene utilizzato come segnaposto seguendo un ifcomando quando non si ha nulla da dire, ma è necessario un comando per consentire al programma di funzionare correttamente. Ma a che cosa serve? Quando lo useresti? Quando ha senso usarlo?



1
Il motivo per cui citi è piuttosto importante. Perché hai bisogno di più?
terdon,

Risposte:


16

A volte è utile consentire gli effetti collaterali delle espansioni dei parametri.

Ad esempio, l'impostazione di un valore predefinito

read -p "Enter your name: " name
: ${name:=John Doe}  # if the user entered an empty string
echo "$name"

2
Potresti spiegare simbolo per simbolo come funziona la seconda riga?
Ruslan,

Leggi il :comando e l' espansione dei parametri nel manuale di bash.
Glenn Jackman,

4
Per delineare ciò a cui fa riferimento @glennjackman, la seconda riga chiama il comando null: e ${name:="John Doe"}verrà espansa, facendo sì che l'assegnazione avvenga perché viene letta come argomento per:. Senza: la shell tenterà di eseguire "John Doe" come comando, o il valore $namese è già impostato
imkendal

13

Puoi anche usarlo per loop infiniti:

while : ; do 
   # ....
done

4
Ma forse while trueè più leggibile, perché (a) usa meno punteggiatura e (b) è più simile ai linguaggi derivati ​​da C.
wchargin,

9

Puoi usarlo per creare un file senza eseguire un programma ::

: > /path/to/file

Questo è infinitamente più veloce di touch /path/to/file (poiché non richiede l'esecuzione del touchprogramma) e può essere leggermente più portatile di un semplice

> /path/to/file

che sembra funzionare su molti sistemi. Allo stesso modo, può essere utilizzato per verificare se si dispone dell'accesso in scrittura a un file :

if { : >> /path/to/file;} 2> /dev/null
then
    echo "writeable"
else
    echo "write permission denied"
fi

sebbene anche questo, generalmente, possa essere fatto senza il :. Avvertenze:

  • Questo non controlla se il file esiste già. In caso contrario, questo creerà il file se dispone dell'autorizzazione per farlo.
  • Se il file non esiste e lo script non dispone dell'autorizzazione per crearlo, verrà segnalato "permesso di scrittura negato".

(Vedi la domanda collegata per i motivi per cui questo è più affidabile di if [ -w /path/to/file ].)


5

Molto tempo fa, in Unix V6 e Thompson Shell, :era effettivamente utilizzato come parte della gotodichiarazione. Secondo il manuale , è apparso originariamente nella versione 3 di Unix:

Nell'intero file di comando viene cercata una riga che inizia con un: come primo carattere non vuoto, seguito da uno o più spazi vuoti, quindi dall'etichetta. Se viene trovata una tale linea, goto riposiziona l'offset del file di comando sulla riga dopo l'etichetta ed esce. Questo fa sì che la shell si trasferisca sulla linea etichettata.

Oggi, in bash, viene utilizzato come operatore no-op, restituendo successo. In effetti, se si guarda il codice sorgente , vedrai che sia truee :utilizzano la stessa funzione, int colon_builtin(), sotto. Non esiste :un comando non incorporato ed /bin/trueè in realtà un comando abbastanza grande per quello che fa.

:potrebbe essere usato ovunque truesia usato, per esempio command_that_can_fail || true, anche se è probabile che confonda i non esperti. Leggi di più qui .


3

Puoi usarlo sul test positivo di un ifcomando quando vuoi solo fare qualcosa sul lato negativo. Per esempio:

if [[ True == False ]]; then
    :
else
    echo "true <> flase"
fi

Senza la :bash si genererebbe un errore di sintassi.

Questo è un esempio semplificato. Generalmente useresti una tale tecnica nella codifica preliminare quando non hai ancora scritto quel segmento di codice e hai solo bisogno di qualcosa che non generi un errore.


Buona risposta, sebbene all'inizio non sia evidente che ciò è molto utile con un comando effettivo all'interno della condizione di test, ad esempio if pgrep firefox >/dev/null ; then : ; else echo "Firefox not running"; fimostrerebbe un errore solo se Firefox non era in esecuzione. In altre parole, quando devi fare qualcosa solo quando il comando ha un errore. In un certo senso ciò equivale pgrep firefox || echo "Firefox not running", sebbene più leggibile e consente più comandi
Sergiy Kolodyazhnyy,

0

L'ho appena usato in uno script con comandi SSH per evitare che lo script si sbagli.

In questo caso, voglio vedere se un utente può connettersi a un set di server. Se la connessione è OK, l'host remoto sarà OK. Se la connessione non riesce, SSH risponderà con l'errore. Tuttavia, voglio che il mio script esca con 0 e non con il valore del comando SSH in caso di errore. Quindi essenzialmente intrappolo l'errore SSH ORing ||con il comando null :. Somiglia a questo:

#!/bin/bash
for i in $(cat servers.txt); do
    echo -n "$i "; 
    ssh user@${i} 'echo OK' || :; 
done

In questo modo ottengo l'output da SSH ma non il codice di errore:

....
swl06 ok
swl07 ok
swl08 Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
swl09 ok
swl10 Permission denied (publickey,gssapi-keyex,gssapi-with-mic,password).
....
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.