Pourquoi le point d'exclamation entre guillemets provoque-t-il une erreur Bash?

23

Veuillez regarder ces commandes:

$ notify-send SYNC TIME!
$ notify-send 'SYNC TIME!'
$ notify-send "SYNC TIME!"
bash: !": event not found
$

Les deux premières commandes produisent une bulle de notification comme prévu. Le troisième donne l'erreur indiquée.

et

$ echo SYNC TIME!
SYNC TIME!
$ echo 'SYNC TIME!'
SYNC TIME!
$ echo "SYNC TIME!"
bash: !": event not found
$

Ici aussi, le echo fonctionne pour les deux premières commandes mais pas pour la troisième.

Plus de problèmes ici (bien que je n’envisage pas de l’utiliser): notify-send "SYNC!TIME" et echo "SYNC!TIME" donnent bash: !TIME": event not found .

Mais notify-send et echo travaillent tous deux avec "SYNC! TIME"

Quelqu'un peut-il s'il vous plaît expliquer pourquoi l'erreur bash: !": event not found apparaît?

    
posée DK Bose 16.03.2014 - 04:15
la source

2 réponses

29

! est le caractère d'extension d'historique par défaut dans Bash, consultez la section "EXPANSION D'HISTOIRE" dans Page de manuel Bash

  • L’expansion de l’historique n’a pas lieu si le ! est entouré de guillemets simples, comme dans

    notify-send 'SYNC TIME!'
    
  • L’expansion de l’historique n’a pas lieu si ! est suivi par un espace, une tabulation, une nouvelle ligne, un retour chariot ou = , comme dans

    notify-send SYNC TIME!
    
  • L’expansion de l’historique fait dans

    echo "SYNC TIME!"
    

    Vous obtenez donc une erreur s’il n’ya pas de commande commençant par " dans votre historique

réponse donnée Florian Diesch 16.03.2014 - 04:36
la source
15

Parce que dans bash, ! est un mot réservé (OK, caractère), il a une signification particulière dans différents contextes. Dans ce cas particulier, vous ne respectez pas sa signification dans la recherche de l’histoire. De man bash :

   History expansions introduce words from the history list into the input
   stream, making it easy to repeat commands, insert the  arguments  to  a
   previous command into the current input line, or fix errors in previous
   commands quickly.

  [...]

   History expansions are introduced by
   the appearance of the  history  expansion  character,  which  is  !  by
   default.   Only  backslash  (\) and single quotes can quote the history
   expansion character.

En gros, cela signifie que bash prendra les caractères après ! et recherchera dans votre historique la première commande trouvée qui commence par ces caractères. Il est plus facile de démontrer que d'expliquer:

$ echo foo
foo
$ !e
echo foo
foo

Extension de l'historique ! activé, correspondant à la première commande commençant par e , qui était précédemment exécutée echo foo , puis exécutée à nouveau. Ainsi, lorsque vous avez écrit "SYNC TIME!" , bash a vu que !" , l'historique des recherches pour une commande commençant par " , a échoué et s'est plaint à ce sujet. Vous pouvez obtenir la même erreur en exécutant, par exemple !nocommandstartswiththis .

Pour imprimer un point d’exclamation, vous devez l’échapper de l’une des deux manières suivantes:

echo 'Hello world!'
echo Hello world\!
    
réponse donnée terdon 16.03.2014 - 04:34
la source

Lire d'autres questions sur les étiquettes