बश में विस्मयादिबोधक चिह्न (!) का उपयोग नहीं कर सकते?


86

मैं !अपने मार्ग में एक विस्मयादिबोधक चिह्न ( ) के साथ http url तक पहुंचने के लिए कर्ल कमांड का उपयोग करने का प्रयास कर रहा हूं । उदाहरण के लिए:

curl -v "http://example.org/!287s87asdjh2/somepath/someresource"

कंसोल उत्तर देता है bash: ... event not found

यहाँ क्या हो रहा है? और विस्मयादिबोधक चिह्न से बचने के लिए उचित वाक्यविन्यास क्या होगा?


बैश में हल किया गया 4.4+
इसहाक

जवाबों:


98

विस्मय बोधक चिह्न बैश में इतिहास विस्तार का हिस्सा है। इसका उपयोग करने के लिए आपको इसे एकल उद्धरणों (जैसे:) में संलग्न करने की आवश्यकता है 'http://example.org/!132'या \चरित्र से पहले एक बैकस्लैश ( ) के साथ इसे सीधे बचने के लिए (जैसे :) "http://example.org/\!132"

ध्यान दें कि दोहरे उद्धरण में, एक्सक्लम से पहले एक बैकस्लैश इतिहास के विस्तार को रोकता है, लेकिन इस तरह के मामले में बैकस्लैश को हटाया नहीं जाता है। इसलिए एकल उद्धरणों का उपयोग करना बेहतर है, इसलिए आप curlURL के भाग के रूप में शाब्दिक बैकस्लैश पास नहीं कर रहे हैं ।


8
"http://example.org/\!132"वास्तव में बैकस्लैश (POSIX अनुपालन कारणों, मुझे विश्वास है) की व्याख्या के बिना फैलता है।
क्रिस डाउन

@ क्रिसडाउन, मैंने स्पष्ट करने की कोशिश की कि पाठ में मेरा दूसरा विकल्प था। भ्रम की संभावना को इंगित करने के लिए धन्यवाद।
डैनियल पिटमैन

6
रिकॉर्ड के लिए: "भागने की कोशिश करना पोर्टेबल नहीं है!"। सर्वोत्तम प्रथाओं की सिफारिश हमेशा उद्धरण (एकवचन-उद्धरण) "" है। संबंधित: "^" (कैरेट), एक गैर-मेटाचैकर है जिसे पोर्टेबिलिटी के लिए उद्धृत करने की आवश्यकता है। आखिरकार, "!" अगर एक बयान में इस्तेमाल नहीं किया जाना चाहिए; यदि संभव हो तो इसके बजाय परीक्षण के तर्क के रूप में उपयोग करें (फिर से सोलारिस / बिन / श के कारण)।
निकोलस विल्सन

5
केवल एक उद्धरण मेरे लिए काम किया। zsh अभी भी दुभाषिया \!और दोहरे उद्धरण चिह्नों की व्याख्या कर रहे थे ।
orkoden

1
सोलारिस पर (पुराने प्री-एक्सपीजी 4 शेल को रगड़ें), '^' के लिए एक उपनाम है |और इसका उपयोग पाइप बनाने के लिए किया जाता है। यदि आप ग्राहकों को स्क्रिप्ट भेज रहे हैं और सुनिश्चित नहीं कर सकते हैं कि वे किस शेल में चलेंगे, तो आपको उन सभी के साथ परीक्षण करना होगा!
निकोलस विल्सन

61

साथ ही डैनियल द्वारा दिए गए उत्तर के साथ, आप इतिहास विस्तार को पूरी तरह से बंद कर सकते हैं यदि आप इसका उपयोग नहीं करते हैं set +H


19
इतिहास के विस्तार को पूरी तरह से बंद करना सबसे अच्छी सलाह है जो मैंने पूरे दिन सुनी है! इतिहास का विस्तार खतरनाक और बीजान्टिन है जब बहुत बेहतर विकल्प होते हैं (वृद्धिशील इतिहास खोज के साथ Ctrl-R) जो आपको अपने आदेश का पूर्वावलोकन और संपादन करते हैं ताकि आप नेत्रहीन रूप से !-14उस आदेश के साथ आग न करें जो आप !-12उस समय थे, उफ़, हुआ rm -rf *। सुरक्षित रहना। इतिहास विस्तार अक्षम करें! Eschew !!
एसुलिच

6
सबसे बड़ा जवाब: इतिहास विस्तार एक बड़ा सुरक्षा जोखिम है! इसका उपयोग आपके यूनिक्स को एक तैयार किए गए URL के माध्यम से हमला करने के लिए किया जा सकता है।
दान

@aculich, या इसके बजाय POSIX- निर्दिष्ट कमांड का fc -14उपयोग करें। लेकिन यह सच है कि आप इतिहास विस्तार के बिना भी सक्षम हो सकते हैं। व्यक्तिगत रूप से, मैं इतिहास विस्तार को सक्षम करने के लिए वारंट का उपयोग करता हूं !$और !viऔर अक्सर पर्याप्त sudo !!भी हूं git add !vi:$
वाइल्डकार्ड

मुझे लगता है कि मैं इसे अपने शेल आरसी फाइलों में जोड़ दूंगा। मैंने इसे केवल एक साफ-सुथरी "ट्रिक" के रूप में इस्तेमाल किया है
टोनीएच

17

मैं व्यक्तिगत रूप से सिंगल कोट्स करूंगा, लेकिन पूर्णता के लिए, मैं इस बात पर भी ध्यान दूंगा क्योंकि यह एक URL है, आप इस !प्रकार %21, जैसे, सांकेतिक शब्दों में बदलना कर सकते हैं curl -v http://example.org/%21132


13

यह भी कर सकते हैं

curl -v "http://example.org/"'!'"287s87asdjh2/somepath/someresource"
या
curl -v "http://example.org/"\!"287s87asdjh2/somepath/someresource"

जो काम करता है क्योंकि बैश आसन्न तारों को समेटता है। यह तरीका विशेष रूप से तब उपयोगी होता है जब आपके पास अन्य चीजें होती हैं जिन्हें शेल विस्तार की आवश्यकता होती है, इसलिए आप पूरे स्ट्रिंग के लिए एकल उद्धरण का उपयोग नहीं कर सकते हैं:

curl -v 'http://example.org/!'"287s87asdjh2/${basepath}/someresource"

!कमांड लाइन प्रॉम्प्ट में इतिहास विस्तार के लिए चरित्र का उपयोग किया जाता है।
इसलिए यह प्रॉम्प्ट में समस्या हो सकती है लेकिन शेल स्क्रिप्ट फ़ाइलों में नहीं।
जैसा कि आप इतिहास के विस्तार को दोहरे उद्धरण चिह्नों में भी काम कर सकते हैं।


यूनिक्स कमांड बनाने के बहुत सारे तरीके हैं और अंग्रेजी वाक्य जरूरत से ज्यादा अक्षरों का उपयोग करते हैं, और जितना होना चाहिए, उससे अधिक भ्रमित होना चाहिए। यह पहले / स्वीकृत / उच्चतम-मत वाले उत्तर से श्रेष्ठ कैसे है, अर्थात् पूरे URL को एकल उद्धरणों में रखा जाए?
जी-मैन

2
@ जी-मैन: यह बैश तर्कों के निर्माण का एक और तरीका बताता है। मुझे इस विधि की जानकारी नहीं थी। नया सामान सीखने में कुछ भी गलत नहीं है।
साहिल सिंह

@SahilSingh यह कैसे नया है? यह तीन तारों को समेटता है, दो दोहरे उद्धरण चिह्नों में और एक एकल उद्धरणों में संलग्न होता है। यहां कोई घोंसला नहीं है।
राफेल

@ जी-मैन यह स्पष्ट नहीं है कि जब आप एक दूसरे के बगल में 2 तार लगाते हैं तो वे मिल जाते हैं। printf ("hello" "world") c में भी काम करेगा, लेकिन printf ("hello" 'w') काम नहीं करेगा, इसलिए आप जानते हैं कि इस तरह के भाव को समझना मेरे लिए नया था, लेकिन मैं इससे सहमत हूं उपयोगिता की दृष्टि से, यह श्रेष्ठ नहीं है। मुझे जवाब पसंद आया, तो मार्क शस्ट ने।
साहिल सिंह

2
@ जी-मैन यह भी उपयोगी है जब वहाँ अन्य स्ट्रिंग विस्तार से एक हैं करता है एक ही स्ट्रिंग में हो करना चाहते हैं। यह दो प्रकार के उद्धरण व्यवहार को अलग करने का एक आसान तरीका है।
WAF

7

मैं एक ही समस्या को लेकर आया हूं, और मेरा सरल समाधान एक चर का उपयोग करना था:

E=!  
curl -v "http://example.org/${E}287s87asdjh2/somepath/someresource"

यहाँ सरलता यह है कि (1) यह गोले और आदेशों में पोर्टेबल है (2) भागने के सिंटैक्स और ASCII कोड को जानने की आवश्यकता नहीं है।


3

कभी बैश 4.3 के बाद से, अब आप इतिहास विस्तार वर्ण को उद्धृत करने के लिए दोहरे उद्धरण चिह्नों का उपयोग कर सकते हैं:

$ bash --version
GNU bash, version 4.3...
[...]
$ echo "Hello World!"
Hello World!

यह बाहर काम नहीं करता है echo, प्रतिध्वनि अपने दम पर इस अलग तरह से संभालने के लिए लगता है
phil294

@Blauhirn यह गूंज के साथ कुछ नहीं करना है, और उद्धरण के साथ सब कुछ करना है और आप चला रहे हैं कि मार के संस्करण।
फ्लिम

2
यह उत्तर गलत है और इसे हटा दिया जाना चाहिए। आपके bashसंस्करण का धमाके के साथ विस्तार नहीं होने से कोई लेना-देना नहीं है, यह इस तथ्य के कारण है कि आपके उदाहरण में !"लाइन का अंत" है और यह शेल को विस्तार करने की कोशिश करने से रोकता है। कोशिश करो echo "!Hello World"और आप देखेंगे कि bashसाथ जवाब देंगे bash: !Hello: event not foundअधिक जानकारी के लिए मैनुअल देखें
don_crissti

0

उन लोगों के लिए जो विंडोज़ में गिट बैश का उपयोग कर रहे हैं, @DanielPittman से स्वीकृत उत्तर काम करता है। हालाँकि, आपको बैकस्लैश (\) को फ़ॉरवर्ड स्लैश (/) से बदलना चाहिए।

उदाहरण के लिए, यूनिक्स में, यह कुछ इस तरह दिखेगा:

curl https://abc.com/services -H 'Authorization: Bearer 111A80BBZZCnS\!ZR412543s'

खिड़कियों के लिए, यह कुछ इस तरह होगा (प्राधिकरण शीर्ष लेख भाग में आगे स्लैश पर ध्यान दें)

curl https://abc.com/services -H 'Authorization: Bearer 111A80BBZZCnS/!ZR412543s'


यह बहुत मतलब नहीं है। आपके पास तर्क एकल उद्धृत है, इसलिए इसमें शामिल स्लैम की परवाह किए बिना एक्सेल में इतिहास विस्तार नहीं होगा।
वाइल्डकार्ड

ओहो तुम सही हो। मैंने केवल इस उत्तर को पोस्ट किया क्योंकि जब मैं डैनियल के उत्तर (बैकस्लैश का उपयोग कर रहा था) का उपयोग कर रहा था, तो एक त्रुटि सामने आती है।
शमूएलदेव
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.