À quoi sert l'opérateur bash Null «:», deux points?

13

Quel est l'intérêt de l'opérateur "null" dans un script BASH? Je comprends qu'il est utilisé comme espace réservé après une ifcommande lorsque vous n'avez rien à dire, mais que vous avez besoin d'une commande pour permettre au programme de fonctionner correctement. Mais quelle en est l'utilité globale? Quand l'utiliseriez-vous? Quand est-il judicieux de l'utiliser?

Justin
la source
1
La raison que vous citez est assez importante. Pourquoi en avez-vous besoin de plus?
terdon

Réponses:

16

Il est parfois utile de permettre aux effets secondaires d'extension de paramètres de se produire.

Par exemple, définir une valeur par défaut

read -p "Enter your name: " name
: ${name:=John Doe}  # if the user entered an empty string
echo "$name"
glenn jackman
la source
2
Pourriez-vous expliquer, symbole par symbole, comment fonctionne la deuxième ligne?
Ruslan
Lisez à propos de l' expansion des :commandes et des paramètres dans le manuel bash.
glenn jackman
4
Pour décrire ce à quoi fait référence @glennjackman, la deuxième ligne appelle la commande null:, et ${name:="John Doe"}sera développée, provoquant l'affectation car elle est lue comme un argument pour :. Sans le: le shell tentera d'exécuter "John Doe" en tant que commande, ou la valeur $namesi elle est déjà définie
imkendal
13

Vous pouvez également l'utiliser pour des boucles sans fin:

while : ; do 
   # ....
done
choroba
la source
4
Mais peut while true- être est plus lisible, car (a) il utilise moins de ponctuation, et (b) il est plus similaire aux langages dérivés C.
wchargin
9

Vous pouvez l'utiliser pour créer un fichier sans exécuter de programme ::

: > /path/to/file

Ceci est infiniment plus rapide que touch /path/to/file (car il ne nécessite pas d'exécuter le touchprogramme) et peut être légèrement plus portable que tout simplement

> /path/to/file

qui semble fonctionner sur de nombreux systèmes. De même, il peut être utilisé pour vérifier si vous avez un accès en écriture à un fichier :

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

bien que cela, aussi, puisse généralement être fait sans :. Mises en garde:

  • Cela ne vérifie pas si le fichier existe déjà. Si ce n'est pas le cas, cela créera le fichier s'il est autorisé à le faire.
  • Si le fichier n'existe pas et que votre script n'est pas autorisé à le créer, cela signale «autorisation d'écriture refusée».

(Voir la question liée pour les raisons pour lesquelles cela est plus fiable que if [ -w /path/to/file ].)

G-Man dit «Réintègre Monica»
la source
5

En arrière, dans Unix V6 et Thompson Shell, le :était en fait utilisé dans le cadre de la gotodéclaration. Selon le manuel , il est apparu à l'origine dans la version 3 d'Unix:

L'ensemble du fichier de commandes est recherché pour une ligne commençant par a: comme premier caractère non vide, suivi par un ou plusieurs blancs, puis l'étiquette. Si une telle ligne est trouvée, goto repositionne le décalage du fichier de commandes sur la ligne après l'étiquette et quitte. Cela provoque le shell à transférer vers la ligne étiquetée.

De nos jours, en bash, il est utilisé comme un opérateur sans opération, retournant le succès. En effet, si vous regardez le code source , vous verrez que les deux trueet :utilisent la même fonction, int colon_builtin()en dessous. Il n'y a :pas de commande non intégrée et /bin/trueest en fait une commande assez importante pour ce qu'elle fait.

:pourrait être utilisé n'importe où trueest utilisé, par exemple dans command_that_can_fail || true, bien que cela risque de dérouter les non-experts. En savoir plus ici .

Sergiy Kolodyazhnyy
la source
3

Vous pouvez l'utiliser sur le test positif d'une ifcommande lorsque vous voulez seulement faire quelque chose de négatif. Par exemple:

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

Sans le : bash, une erreur de syntaxe serait générée.

Ceci est un exemple trop simplifié. Généralement, vous utiliseriez une telle technique dans le codage préliminaire lorsque vous n'avez pas encore écrit ce segment de code et que vous avez juste besoin de quelque chose qui ne génère pas d'erreur.

WinEunuuchs2Unix
la source
Bonne réponse, bien que cela ne soit pas évident au premier abord, que cela est plus utile avec une commande réelle dans la condition de test, par exemple, if pgrep firefox >/dev/null ; then : ; else echo "Firefox not running"; fine montrerait d'erreur que si firefox n'était pas en cours d'exécution. En d'autres termes, lorsque vous devez faire quelque chose uniquement lorsque la commande contient une erreur. D'une certaine manière, cela équivaut à pgrep firefox || echo "Firefox not running", bien que plus lisible et autorise plus de commandes
Sergiy Kolodyazhnyy
0

Je viens de l'utiliser dans un script avec des commandes SSH pour empêcher le script de générer des erreurs.

Dans ce cas, je veux voir si un utilisateur peut se connecter à un ensemble de serveurs. Si la connexion est OK, l'hôte distant fera écho OK. Si la connexion échoue, SSH répondra avec l'erreur. Cependant, je veux que mon script se termine avec 0 et non la valeur de la commande SSH en cas d'échec. Donc, essentiellement, je piège l'erreur SSH en l'ORing ||avec la commande null :. Ressemble à ça:

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

De cette façon, j'obtiens la sortie de SSH mais pas le code d'erreur:

....
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).
....
Michael J
la source