Question Qu'est-ce que “-bash:!”: Événement non trouvé "


Essayez d’exécuter ce qui suit sous un shell bash echo "Reboot your instance!"

Sur mon installation:

root@domU-12-31-39-04-11-83:/usr/local/bin# bash --version
GNU bash, version 4.1.5(1)-release (i686-pc-linux-gnu)
Copyright (C) 2009 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
root@domU-12-31-39-04-11-83:/usr/local/bin# uname -a
Linux domU-12-31-39-04-11-83 2.6.35-22-virtual #35-Ubuntu SMP Sat Oct 16 23:57:40 UTC 2010 i686 GNU/Linux
root@domU-12-31-39-04-11-83:/usr/local/bin# echo "Reboot your instance!"
-bash: !": event not found

Quelqu'un peut-il s'il vous plaît expliquer ce que sont les "événements bash?" Je n'ai jamais entendu ce concept auparavant. Aussi, comment devrais-je sortir "!" à la fin de la phrase?


88
2017-12-02 10:45


origine




Réponses:


Vous pouvez désactiver la substitution d'historique à l'aide de set +H.


40
2017-12-02 16:31



Connaissez-vous le raisonnement derrière la syntaxe? Cela semble vraiment contre-intuitif. Vous penseriez taper +H pour permettre quelque chose et -H désactiver quelque chose. - PunkyGuy
@PunkyGuy: Je ne connais pas l'historique (jeu de mots voulu), mais les options Unix commencent généralement par un trait d'union (ou moins) et + est simplement le contraire de cela. - Dennis Williamson


! est un caractère spécial à bash, il est utilisé pour faire référence aux commandes précédentes; par exemple,

!rm

va rappeler et exécuter la dernière commande qui a commencé avec la chaîne "rm", et

!rm:p

rappellera mais n'exécutera pas la dernière commande qui a commencé avec la chaîne "rm". bash interprète le point d'exclamation echo "reboot your instance!" comme "remplacez ici la dernière commande qui a commencé par le ou les caractère (s) immédiatement après le point d'exclamation", et se lamente contre le fait qu’il ne puisse pas trouver un événement (commande) dans votre historique qui a commencé par une simple citation double.

Essayer

echo reboot your instance\!

protéger (échapper) le point d'exclamation de bash.


86
2017-12-02 10:49



Oui, mais cela devrait arriver si je veux utiliser echo -e "du texte $ ENV_VAL un peu plus de texte \ nReboot maintenant!" ? - Maxim Veksler
Écrivez deux déclarations d'écho; vous recevez le saut de ligne gratuitement. - MadHatter
La solution simple consiste à utiliser des guillemets simples et des guillemets doubles à la fois: echo -e "Text \ nReeboot" '!' - mmey
Ça craint. Si je n'échappe pas au point d'exclamation, bash me fait mal. Si je faire pour l’échapper, la barre oblique inverse est incluse dans la dernière chaîne. Pourquoi faites-vous cela, Bash !! (pastebin.com/g4PYv56A) - Hubro
@Hubro en toute justice, je ne suis pas sûr que tout soit de la faute de bash. Vous avez quelque chose de compliqué à utiliser le rubis pour alimenter des choses à critiquer, et je ne vois pas très bien quel rôle joue le rubis dans l'élimination ou le renforcement des personnages de l'évasion. - MadHatter


Pour résoudre votre problème initial, essayez d'utiliser des guillemets simples plutôt que des guillemets doubles. Avec ce dernier, bash tentera de développer certains caractères avant de transmettre le résultat à la commande (echo dans ce cas). Avec des guillemets simples, bash passe la chaîne entière sans aucune modification.

! est utilisé dans les commandes pour faire référence à l'historique de ligne de commande. Voir: http://tldp.org/LDP/abs/html/abs-guide.html#HISTCOMMANDS pour un ensemble complet. Avec l'exemple ci-dessus, bash essaie de se développer !" en tant que référence à un événement avant que l'écho soit examiné, d'où l'erreur.

Notez que dans les scripts, tout des commandes d'historique sont désactivées, car elles n'ont de sens que dans un shell interactif.

Le seul que j'utilise régulièrement, c'est !$. Il se développe jusqu'au dernier argument de la commande précédente. C'est un raccourci utile dans certains endroits.


22
2017-12-02 11:02



!! remplir la dernière commande complète entrée est remarquablement utile; particulièrement, sudo !! ou pfexec !! - jgoldschrafe
Je trouve également que sudo et pfexec sont de bons utilitaires, mais nul besoin d’être aussi enthousiastes. - LeartS
$_ fonctionne dans plus de coquilles que bash et c'est une variable appropriée, contrairement à !$. (et @LeartS: J'ai bien aimé le manque d'émoticônes de votre blague.;)) - ΤΖΩΤΖΙΟΥ


Il suffit de mettre un espace entre! et "que ça va marcher.

À votre santé.


5
2017-09-25 07:06



Pourriez-vous s'il vous plaît ajouter une explication quant à pourquoi votre solution fonctionne? - 200_success
Cela fonctionne parce que Bash ne traite que! en tant que caractère spécial s'il est directement suivi d'un caractère non blanc. Cependant, cela ajoutera également un blanc supplémentaire à votre sortie, de sorte que cela ne soit pas toujours souhaitable ... - mmey


Oui, ! est un caractère spécial à bash, il est utilisé pour faire référence aux commandes précédentes.

Peu de façons de gérer la situation

Ce qui suit va afficher la chaîne telle quelle.

echo 'Reboot your instance!'

Ce qui suit va exécuter la commande et concaténer la chaîne

echo 'escaping #'" adding `which python` to the string"
echo '#!'`which python`

2
2018-04-25 13:57





Dans bash 4.3 il semble que vous n'ayez plus besoin d'utiliser des guillemets simples ou set +H:

$ bash --version
GNU bash, version 4.3.46(1)-release (x86_64-unknown-linux-gnu)
[...]
$ echo "Reboot your instance!"
Reboot your instance!

1
2017-07-12 14:43



Probablement un bug, car ici, j'ai 4.4.12 et encore, il me faut set +H ou en citant. Ou vous avez set +H quelque part (comme dans /etc/profile). - Bodo Thiesen
Utiliser! -Char pas à la fin de la phrase vérifie que la détection d'événements de bash fonctionne toujours correctement. La version est 4.3.30 ........ $ echo "Revérifiez votre phrase! Foo" bash:! Foo: événement non trouvé - JohnnyD92


Vous pouvez aussi utiliser un Heredoc:

cat <<EOF
Reboot your instance!
EOF

C'est agaçant dans ce cas parce que ce n'est pas un one-liner mais pour des commandes plus longues (comme écrire un script bash), cela fonctionne très bien.


0
2017-07-07 11:41