दोहरे उद्धरण चिह्नों के भीतर विस्मयादिबोधक चिह्न बैश त्रुटि का कारण क्यों बनता है?


25

कृपया इन आदेशों को देखें:

$ 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-sendऔर echoसाथ काम करते हैं"SYNC! TIME"

क्या कोई यह बता सकता है कि bash: !": event not foundत्रुटि क्यों दिखाई देती है?

जवाबों:


31

!बश में डिफ़ॉल्ट इतिहास विस्तार चरित्र है, बाश मैनपेज में "इतिहास विस्तार" अनुभाग देखें

  • यदि !एक एकल उद्धरण द्वारा संलग्न किया गया है, तो इतिहास विस्तार नहीं होता है

    notify-send 'SYNC TIME!'
  • यदि !किसी स्थान, टैब, न्यूलाइन, कैरिज रिटर्न, या =, जैसे के बाद इतिहास विस्तार नहीं होता है

    notify-send SYNC TIME!
  • इतिहास का विस्तार होता है

    echo "SYNC TIME!"

    यदि "आपके इतिहास में कोई कमांड नहीं है तो आपको एक त्रुटि मिलेगी


4
इस दुर्व्यवहार को आपकी .bashrcपंक्ति में जोड़कर तय किया जा सकता है set +H। ध्यान दें कि !स्क्रिप्टिंग में पहले से ही गैर-विशेष है; इसे विशेष मानकर कई मानकों के अनुरूप स्क्रिप्ट को तोड़ा जाएगा। यह केवल इंटरैक्टिव गोले में "विशेष" के रूप में माना जाता है, और केवल डिफ़ॉल्ट रूप से जब तक आप इसे ठीक नहीं करते। :-)
आर ..

15

क्योंकि बाश में, !एक आरक्षित शब्द (ओके, चरित्र) है, इसका अलग-अलग संदर्भों में विशेष अर्थ है। इस विशेष मामले में, आप इतिहास की खोज में इसके महत्व को कम कर रहे हैं। से 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.

मूल रूप से, इसका मतलब यह है कि बैश पात्रों के बाद ले जाएगा !और अपने इतिहास को उन कमांड्स के साथ शुरू होने वाली पहली कमांड के लिए खोजेगा। यह समझाने की तुलना में प्रदर्शित करना आसान है:

$ echo foo
foo
$ !e
echo foo
foo

!सक्रिय इतिहास विस्तार है, जो के साथ शुरू पहले आदेश का मिलान नहीं हुआ eजो पहले से चलाने था echo fooजो उसके बाद फिर से चलाया गया था। इसलिए, जब आपने लिखा "SYNC TIME!", तो बैश ने देखा !", के साथ शुरू होने वाले कमांड के लिए इतिहास खोजा ", विफल रहा और इसके बारे में शिकायत की। उदाहरण के लिए, आप उसी त्रुटि को चलाकर प्राप्त कर सकते हैं !nocommandstartswiththis

विस्मयादिबोधक चिह्न मुद्रित करने के लिए, आपको इन दो तरीकों में से एक में बचना होगा:

echo 'Hello world!'
echo Hello world\!

6
echo Hello world!काम करता है --- इतिहास विस्तार
ब्लैंक

1
हालांकि, खाली जगह की तुलना में विस्मयादिबोधक चिह्न से बचने पर भरोसा करना बेहतर है।
एहतेश चौधरी

1
@Rmano मैं स्पष्ट रूप से एक व्यवहार के मार्गदर्शक के बजाय ऐसा कहना पसंद करता हूं जिसे बदलना संभव है
Braiam

!एक आरक्षित शब्द है bash, जैसा कि POSIX भी घोषित करता है । लेकिन मुझे पूरा यकीन है कि इसकी स्थिति इतिहास विस्तार में इसकी भूमिका से पूरी तरह से असंबंधित है और दोहरे उद्धरण चिह्नों में इसके उपचार के लिए अप्रासंगिक है। !एक आरक्षित शब्द है क्योंकि यह एक कमांड / पाइपलाइन की निकास स्थिति को नकारता है, इसलिए इसे कमांड के रूप में उपयोग नहीं किया जा सकता है। किसी भी अन्य आरक्षित शब्द को एक विशेष शब्द के "संदर्भ में विशेष नहीं$ है , जबकि एक आरक्षित शब्द नहीं है , लेकिन विशेष रूप से व्यवहार किया जाता है।
एलिया कगन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.