जवाबों:
संक्षिप्त जवाब
जैसे दूसरों ने कहा है - आपको हमेशा अजीब व्यवहार को रोकने के लिए चर का उद्धरण देना चाहिए। तो इको "$ फू" की बजाय सिर्फ इको $ फू का उपयोग करें ।
लंबा जवाब
मुझे लगता है कि यह उदाहरण आगे की व्याख्या करता है क्योंकि इससे कहीं अधिक चल रहा है क्योंकि यह उसके चेहरे पर लग सकता है।
मैं देख सकता हूं कि आपका भ्रम कहां है क्योंकि आपने अपना पहला उदाहरण चलाने के बाद शायद आपने खुद से सोचा था कि शेल स्पष्ट रूप से कर रहा है:
तो अपने पहले उदाहरण से:
me$ FOO="BAR * BAR"
me$ echo $FOO
पैरामीटर विस्तार के बराबर है:
me$ echo BAR * BAR
और फ़ाइल नाम विस्तार के बराबर है:
me$ echo BAR file1 file2 file3 file4 BAR
और यदि आप केवल echo BAR * BAR
कमांड लाइन में टाइप करते हैं, तो आप देखेंगे कि वे समकक्ष हैं।
तो आप शायद अपने आप को "अगर मैं * से बचता हूं, तो मैं फ़ाइल नाम के विस्तार को रोक सकता हूं"
तो अपने दूसरे उदाहरण से:
me$ FOO="BAR \* BAR"
me$ echo $FOO
पैरामीटर विस्तार के बाद के बराबर होना चाहिए:
me$ echo BAR \* BAR
और फ़ाइल नाम के विस्तार के बराबर होना चाहिए:
me$ echo BAR \* BAR
और यदि आप सीधे कमांड लाइन में "इको बार \ * बार" टाइप करने की कोशिश करते हैं, तो यह वास्तव में "BAR * BAR" प्रिंट करेगा क्योंकि फ़ाइल नाम के विस्तार से बच जाता है।
तो $ फू का उपयोग क्यों नहीं किया?
ऐसा इसलिए है क्योंकि इसमें तीसरा विस्तार है - उद्धरण हटाना। बैश मैनुअल उद्धरण हटाने से है:
पूर्ववर्ती विस्तार के बाद, वर्णों के सभी अनियोजित घटनाएं '\', '' 'और' '' 'जिसके परिणामस्वरूप उपरोक्त में से एक भी परिणाम नहीं निकाला जाता है।
तो क्या होता है जब आप कमांड लाइन में सीधे कमांड टाइप करते हैं, तो एस्केप कैरेक्टर पिछले विस्तार का परिणाम नहीं होता है, इसलिए B इसे इको कमांड में भेजने से पहले हटा देता है, लेकिन दूसरे उदाहरण में, "\ *" था पिछले पैरामीटर विस्तार का परिणाम है, इसलिए इसे हटाया नहीं गया है। परिणामस्वरूप, प्रतिध्वनि "\ *" प्राप्त करती है और यही वह प्रिंट करता है।
पहले उदाहरण के बीच अंतर पर ध्यान दें - "*" उन पात्रों में शामिल नहीं है जिन्हें उद्धरण हटाने के द्वारा हटा दिया जाएगा।
मुझे लगता है कि इसका मतलब बनता है। अंत में उसी में निष्कर्ष - बस उद्धरण का उपयोग करें। मैंने सोचा था कि मैं समझाऊंगा कि बचना क्यों चाहिए, जो तार्किक रूप से काम करना चाहिए अगर केवल पैरामीटर और फाइलनेम का विस्तार खेल में हो, काम नहीं किया।
BASH विस्तार की पूरी व्याख्या के लिए, यहां देखें:
http://www.gnu.org/software/bash/manual/bashref.html#Shell-Expansions
मैं इस पुराने सूत्र में थोड़ा जोड़ दूंगा।
आमतौर पर आप उपयोग करते होंगे
$ echo "$FOO"
हालाँकि, मुझे इस सिंटैक्स से भी समस्याएँ हैं। निम्नलिखित स्क्रिप्ट पर विचार करें।
#!/bin/bash
curl_opts="-s --noproxy * -O"
curl $curl_opts "$1"
*
आवश्यकताओं के शब्दशः पारित होने के लिए curl
, लेकिन एक ही समस्या आने पर होगा। उपरोक्त उदाहरण काम नहीं करेगा (यह मौजूदा निर्देशिका में फ़ाइल नाम में विस्तार करेगा) और न ही होगा \*
। आप यह भी उद्धृत नहीं कर सकते $curl_opts
क्योंकि इसे एकल (अमान्य) विकल्प के रूप में मान्यता दी जाएगी curl
।
curl: option -s --noproxy * -O: is unknown
curl: try 'curl --help' or 'curl --manual' for more information
इसलिए मैं वैश्विक पैटर्न पर लागू होने पर फ़ाइल नाम के विस्तार को रोकने के लिए bash
चर के उपयोग की सिफारिश करूंगा $GLOBIGNORE
या set -f
निर्मित ध्वज का उपयोग करूंगा ।
#!/bin/bash
GLOBIGNORE="*"
curl_opts="-s --noproxy * -O"
curl $curl_opts "$1" ## no filename expansion
अपने मूल उदाहरण पर लागू:
me$ FOO="BAR * BAR"
me$ echo $FOO
BAR file1 file2 file3 file4 BAR
me$ set -f
me$ echo $FOO
BAR * BAR
me$ set +f
me$ GLOBIGNORE=*
me$ echo $FOO
BAR * BAR
SELECT * FROM etc.
, यह एकमात्र तरीका है जो काम करता है।
echo "$FOO"
यह कमांड लाइन पर printf
नहीं बल्कि उपयोग करने की आदत में पड़ने लायक हो सकता है echo
।
इस उदाहरण में यह अधिक लाभ नहीं देता है लेकिन यह अधिक जटिल आउटपुट के साथ अधिक उपयोगी हो सकता है।
FOO="BAR * BAR"
printf %s "$FOO"