Neden çift tırnak içindeki ünlem işareti Bash hatası veriyor?


25

Lütfen şu komutlara bakın:

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

İlk iki komut beklendiği gibi bir bildirim balonu oluşturur. Üçüncüsü gösterilen hatayı verir.

ve

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

Burada da, echoilk iki komut için olan ancak üçüncü değil.

Daha (Ben bu kullanarak planlama değildi rağmen) burada sorunları: hem notify-send "SYNC!TIME"ve echo "SYNC!TIME"vermek bash: !TIME": event not found.

Ama her ikisi de notify-sendve birlikte echoçalışmak"SYNC! TIME"

Birisi lütfen bash: !": event not foundhatanın neden ortaya çıktığını açıklayabilir mi?

Yanıtlar:


31

!Bash'deki varsayılan tarih genişletme karakteridir, Bash manpage'inde "HISTORY EXPANSION" bölümüne bakınız.

  • Geçmiş genişletme !, içinde olduğu gibi tek tırnak işaretleri içine alınmışsa gerçekleşmez .

    notify-send 'SYNC TIME!'
  • Tarihin genişlemesini, !boşluk, sekme, yeni satır, satır başı veya =gibi

    notify-send SYNC TIME!
  • Geçmiş genişleme yapar take place in

    echo "SYNC TIME!"

    Böylece "geçmişinizde başlayacak bir komut yoksa hata alırsınız


4
Bu hatalı davranış .bashrc, hattınıza eklenerek giderilebilir set +H. !Senaryo yazımında zaten özel olmadığını unutmayın ; onu özel olarak kabul etmek, pek çok standarda uygun senaryoyu bozabilir. Yalnızca etkileşimli mermilerde "özel" olarak ve yalnızca düzeltilinceye kadar varsayılan olarak kullanılır. :-)
R. ..

15

Bash'ta, !ayrılmış bir sözcük (Tamam, karakter) olduğu için farklı bağlamlarda özel bir anlamı vardır. Bu özel durumda, tarih arayışındaki öneminden mahrum kalıyorsunuz. Kimden 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.

Temel olarak, bunun anlamı, bash'ın ardından karakterleri alacağı !ve geçmişinizde bu karakterlerle başlayan ilk komutu arayacağıdır. Göstermek açıklamaktan daha kolaydır:

$ echo foo
foo
$ !e
echo foo
foo

!İle başlayan ilk komutu eşleşti aktive tarih genişleme, ehangi önceden çalıştırmak oldu echo foosonra tekrar çalıştırıldığı. Böylece, yazdığınızda "SYNC TIME!", bash !", onunla başlayan bir komut için aranan tarihi gördü ", başarısız oldu ve bundan şikayet etti. Örneğin, aynı hatayı çalıştırarak alabilirsiniz !nocommandstartswiththis.

Bir ünlem işareti basmak için, aşağıdaki iki yoldan biriyle kaçmanız gerekir:

echo 'Hello world!'
echo Hello world\!

6
echo Hello world!iş --- tarih genleşme boşlukları ;-) (ah güzel köşe vakalar ...) tarafından tetiklenmez gelmez
Rmano

1
Ünlem işaretinden kaçmaya güvenmek, boşluklardan ziyade daha iyidir.
Ehtesh Choudhury 16.04

1
@Rmano Açıkça söylemek istediğim bir şey değil, bana değişmesi muhtemel bir davranış konusunda rehberlik etmekten çok
hoşlanıyorum

!Bir olan özel amaçlı sözcük içinde basholduğu gibi, POSIX da beyan . Ancak, biri olarak statüsünün , tarihin genişlemesindeki rolü ile tamamen ilgili olmadığı ve çift tırnak içindeki tedavisi ile alakasız olduğundan eminim . !ayrılmış bir kelimedir çünkü bir komut / boru hattının çıkış durumunu iptal eder, bu nedenle komut olarak kullanılamaz. Başka hiçbir özel amaçlı sözcük bir özel olduğunu "iken, -quoted bağlamda $olduğu değil , ayrılmış bir sözcük ama edilmektedir özel olarak ele.
Eliah Kagan
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.