À quoi sert la saisie d'un seul point d'exclamation dans Bash?

20

Bash utilise des points d'exclamation pour les extensions d'historique, comme expliqué dans les réponses à cette question (par exemple, sudo !!exécute la ligne de commande précédente avec sudo). Cependant, je ne trouve nulle part qui explique ce que fait l'exécution de la commande suivante (c'est-à-dire un seul point d'exclamation):

!

Il semble ne rien imprimer et sortir avec 1, mais je ne sais pas pourquoi il fait cela. J'ai regardé en ligne et dans la page de manuel de Bash, mais je ne trouve rien, à part le fait que c'est un "mot réservé" - mais c'est le cas }, et en exécutant ceci:

}

imprime une erreur:

bash: syntax error near unexpected token `}'
Josh
la source
1
Rien. !indique le "début" d'une expression d'extension d'historique.
jordanm

Réponses:

47

Le seul !au début d'une commande annule l'état de sortie de la commande ou du pipeline : si la commande se termine 0, elle basculera en 1(échec), et si elle sort non nulle, elle le transformera en une 0sortie (réussie).

Cette utilisation est documentée dans le manuel Bash:

Si le mot réservé "!" précède le pipeline, l'état de sortie est la négation logique de l'état de sortie comme décrit ci-dessus.

Un !sans commande suivante annule la commande vide, qui ne fait rien et retourne vrai (équivalent à la :commande ). Il inverse ainsi le vrai en faux et quitte avec le statut 1, mais ne produit aucune erreur.


Il existe également d'autres utilisations de !dans les commandes testet [[, où elles annulent un test conditionnel. Ceux-ci ne sont pas liés à ce que vous voyez. Dans votre question et dans ces cas, cela n'est pas lié à l'expansion de l'histoire et !est séparé de tout autre terme.

Michael Homer
la source
5
+1 pour la première réponse pour expliquer ce qui est réellement exécuté et pourquoi cela explique le code retour.
Jeff Schaller
11

Vous pouvez trouver le point d'exclamation unique documenté dans la section 3.2.2 Pipelines du manuel bash

Si le mot réservé "!" précède le pipeline, l'état de sortie est la négation logique de l'état de sortie comme décrit ci-dessus.

$ ! true; echo $?
1
$ ! false; echo $?
0

Section 3.2.4.2 Constructions conditionnelles également

! expression

Vrai si l'expression est fausse.


Section 4.1 Bourne Shell Builtins

! expr

Vrai si expr est faux.


Il convient également de noter que la !substitution d'historique démarrera à moins d'être suivie par: un espace, une tabulation, la fin de la ligne, '=' ou '(' (lorsque l'option shell extglob est activée à l'aide de la fonction intégrée shopt).

Jesse_b
la source
0

Parce que !est utilisé dans les comparaisons et signifie NON .

Par exemple:

a=3
b=2

[ $a -eq $b ] && echo "Equal"
[ ! $a -eq $b ] && echo "Not equal"
# of cause last comparison is possible to write as:
[ $a -eq $b ] || echo "Not equal"

[ $a -eq $b ]
echo $?
1
[ ! $a -eq $b ]
echo $?
0
Yurij Goncharuk
la source
1
C'est la signification de !comme argument de la testcommande (y compris la version intégrée de bash), et non la signification de !lorsqu'il est utilisé en position de commande.
Gilles 'SO- arrête d'être méchant'
1
Il faudrait que cela corresponde ! [...]à la question dans ce cas.
Michael Homer
En accord avec @Gilles et @Michael Homer. Je savais que []c'est test. Je suis un peu pressé.
Yurij Goncharuk
-2

! commande intégrée, inverse le sens d'un pipeline.

Autres utilisations:

#! commande intégrée, appelle l'interpréteur nommé pour exécuter le script.

! désignateur d'événement, marque un mot de ligne de commande comme substitution d'historique

!= opérateur d'inégalité

$! variable shell, retourne le numéro de processus de la dernière commande en arrière-plan.

Bharat
la source
Juste pour ajouter, on peut utiliser! $ Pour utiliser le dernier mot de la commande précédente comme ceci: ls -l /tmp cd !$ Cela vous amènera au répertoire / tmp.
Hopping Bunny
-3

! suivi d'une chaîne exécute la commande précédente la plus récente (toujours dans le tampon de commande) qui a commencé avec la chaîne donnée. Peut-être que le shell vient de découvrir qu'aucune commande précédente n'a commencé par <null>.

pdelmonte
la source
3
Vous avez remarqué qu'il n'y avait pas de chaîne donnée dans la question ...?
Jeff Schaller