當前位置: 首頁>>技術教程>>正文


為什麽雙引號中的感歎號會導致Bash錯誤?

問題描述

請查看以下命令:

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

前兩個命令按預期產生通知氣泡。第三個給出顯示的錯誤。

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

同樣在這裏,echo適用於前兩個命令,但不適用於第三個命令。

這裏還有更多問題(盡管我不打算使用它):notify-send "SYNC!TIME"echo "SYNC!TIME"都給出bash: !TIME": event not found

但是notify-sendecho均可與"SYNC! TIME"一起使用

有人可以解釋為什麽出現bash: !": event not found錯誤嗎?

最佳辦法

!是Bas​​h中的默認曆史記錄擴展字符,請參閱Bash manpage中的”HISTORY EXPANSION”部分

  • 如果!用單引號引起來,則不會進行曆史擴展,例如

    notify-send 'SYNC TIME!'
    
  • 如果!後跟一個空格,製表符,換行符,回車符或=,則不會進行曆史記錄擴展,如

    notify-send SYNC TIME!
    
  • 曆史擴展確實發生在

    echo "SYNC TIME!"
    

    因此,如果您的曆史記錄中沒有以"開頭的命令,則會出現錯誤

次佳辦法

因為在bash中,!是保留字(OK,字符),所以它在不同的上下文中具有特殊的含義。在這種情況下,您將無法理解其在曆史搜索中的重要性。從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.

基本上,這意味著bash將在!之後獲取字符,並在曆史記錄中搜索它發現的以這些字符開頭的第一個命令。演示比解釋容易:

$ echo foo
foo
$ !e
echo foo
foo

!已激活的曆史記錄擴展,與第一個以e開始的命令匹配,該命令是先前運行的echo foo,然後又運行了。因此,當您編寫"SYNC TIME!"時,bash看到了!",在曆史記錄中搜索了以"開頭的命令,但失敗並提出了抱怨。您可以通過運行例如!nocommandstartswiththis來獲得相同的錯誤。

要打印感歎號,您需要通過以下兩種方式之一對其進行轉義:

echo 'Hello world!'
echo Hello world\!

參考資料

本文由Ubuntu問答整理, 博文地址: https://ubuntuqa.com/zh-tw/article/11618.html,未經允許,請勿轉載。