Che cos'è "-bash:!": Evento non trovato "


114

Prova a eseguire quanto segue sotto una shell bash echo "Reboot your instance!"

Sulla mia installazione:

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

Qualcuno può spiegare cosa sono gli "eventi bash"? Non ho mai sentito questo concetto prima. Inoltre, come devo generare "!" alla fine della frase?

Risposte:


53

È possibile disattivare la sostituzione della cronologia utilizzando set +H.


2
Conosci il ragionamento alla base della sintassi? Sembra davvero contro intuitivo. Penseresti di digitare +Hper abilitare qualcosa e -Hdisabilitare qualcosa.
Gavin Ward,

7
@PunkyGuy: Non conosco la storia (gioco di parole intenzionale) dietro di essa, ma le opzioni Unix in genere iniziano con un trattino (o meno) ed +è semplicemente il contrario.
Dennis Williamson,

105

!è un carattere speciale da bash, è usato per riferirsi a comandi precedenti; per esempio,

!rm

richiamerà ed eseguirà l'ultimo comando iniziato con la stringa "rm", e

!rm:p

richiamerà ma non eseguirà l'ultimo comando iniziato con la stringa "rm". bash sta interpretando il punto esclamativo echo "reboot your instance!"come " sostituisci qui l'ultimo comando che è iniziato con il / i carattere / i immediatamente dopo il punto esclamativo " e ti brontola che non è possibile trovare un evento (comando) nella tua storia che inizi con un singolo doppio preventivo.

Provare

echo reboot your instance\!

per proteggere (sfuggire) al punto esclamativo da bash.


Sì, ma dovrebbe succedere se voglio usare echo -e "un po 'di testo $ ENV_VAL un altro po' di testo \ nRiavviare ora!" ?
Maxim Veksler,

1
Scrivi due dichiarazioni di eco; ricevi il feed di linea gratuitamente.
MadHatter,

1
La soluzione semplice consiste nell'utilizzare virgolette singole e doppie tra loro contemporaneamente: echo -e "Text \ nReeboot" '!'
mmey

4
Questo fa schifo. Se non sfuggo al punto esclamativo, bash lancia un attacco. Se mi faccio sfuggire, il backslash è incluso nella stringa finale. Perché lo fai, Bash !! ( pastebin.com/g4PYv56A )
Hubro

2
@Hubro in tutta onestà, non sono sicuro che sia tutta colpa di Bash. Hai delle questioni piuttosto complicate usando il rubino per alimentare le cose da colpire, e non mi è chiaro quale parte stia giocando il rubino nello spogliare o rafforzare i personaggi di fuga.
MadHatter,

25

Per risolvere il problema originale, prova a utilizzare virgolette singole anziché doppie. Con quest'ultimo, bash tenterà di espandere determinati caratteri prima di passare il risultato al comando (echo in questo caso). Con virgolette singole, bash passa l'intera stringa, invariata.

!viene utilizzato nei comandi per fare riferimento alla cronologia della riga di comando. Vedi: http://tldp.org/LDP/abs/html/abs-guide.html#HISTCOMMANDS per un set completo. Con l'esempio sopra, bash sta cercando di espandersi !"come riferimento a un evento prima che l'eco dia un'occhiata, da cui l'errore.

Si noti che negli script, tutti i comandi della cronologia sono disabilitati, poiché hanno senso solo in una shell interattiva.

L'unico che uso regolarmente è !$. Si espande fino all'ultimo argomento del comando precedente. È una scorciatoia utile in alcuni punti.


4
!!compilare l'ultimo comando completo inserito è straordinariamente utile; in particolare, sudo !!oppurepfexec !!
jgoldschrafe il

2
Trovo anche che sudo e pfexec siano utili programmi di utilità, ma non è necessario essere così entusiasti.
LeartS

$_funziona in più shell di bash ed è una variabile corretta, a differenza !$. (e @LeartS: Mi è piaciuta la mancanza di emoticon della tua battuta.;))
ΤΖΩΤΖΙΟΥ

7

Metti solo uno spazio tra! e "che funzionerà.

Saluti.


2
Potresti aggiungere una spiegazione sul perché la tua soluzione funziona?
200_successo

2
Questo funziona perché Bash tratta solo! come carattere speciale se è seguito direttamente da un carattere non bianco. Tuttavia, aggiungerà anche uno spazio in più all'output, quindi potrebbe non essere sempre desiderato ...
mmey

2

Sì, ! è un carattere speciale da colpire, è usato per riferirsi a comandi precedenti.

Pochi modi in cui puoi gestire la situazione

Di seguito verrà generata la stringa così com'è

echo 'Reboot your instance!'

Di seguito eseguirà il comando e concatenerà la stringa

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

1

In bash 4.3quanto pare non c'è più bisogno di utilizzare le virgolette singole o set +H:

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

Probabilmente un bug, perché qui ho 4.4.12 e, ancora una volta, ho bisogno set +Ho preventivo. O hai da set +Hqualche parte (come in /etc/profile).
Bodo Thiesen,

L'uso di! -Char non alla fine della frase verifica che il rilevamento degli eventi di bash funzioni ancora bene. La versione è 4.3.30 ........ $ echo "Ricontrolla la tua frase! Pippo" bash
:! Pippo

0

Puoi anche usare un heredoc :

cat <<EOF
Reboot your instance!
EOF

In questo caso è fastidioso perché non è una riga, ma per comandi più lunghi (come scrivere uno script bash), funziona benissimo.

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.