उद्धृत बनाम विस्तारित स्ट्रिंग विस्तार


11
  1. for i in $(xrandr); do echo "$i" ; done
  2. for i in "$(xrandr)"; do echo "$i"; done
  3. for i in "$(xrandr)"; do echo $i; done

मैं समझता हूँ कि क्यों 1 से अलग है 2. लेकिन 3 क्यों 2 से अलग आउटपुट देता है? कृपया आउटपुट भी समझाएं। कैसे उद्धरण newlines पर काम करते हैं?



जवाबों:


19

(के रूप में एक गैर उद्धृत चर $var) या (के रूप में आदेश प्रतिस्थापन $(cmd)या `cmd`) है विभाजन + ग्लोब में ऑपरेटर बॉर्न की तरह गोले।

यही है, उनकी सामग्री $IFSविशेष चर के वर्तमान मूल्य के अनुसार विभाजित है (जो डिफ़ॉल्ट रूप से स्थान, टैब और न्यूलाइन वर्ण शामिल हैं)

और फिर उस विभाजन के परिणामस्वरूप प्रत्येक शब्द फ़ाइलनाम पीढ़ी ( ग्लोबिंग या फ़ाइलनाम विस्तार के रूप में भी जाना जाता है) के अधीन है , अर्थात, उन्हें पैटर्न के रूप में माना जाता है और उस पैटर्न से मेल खाने वाली फ़ाइलों की सूची में विस्तारित किया जाता है।

तो for i in $(xrandr), में $(xrandr), क्योंकि यह उद्धरण के भीतर नहीं है, अंतरिक्ष, टैब और newline वर्णों के अनुक्रम पर विभाजित है। और उस बंटवारे के परिणामस्वरूप होने वाले प्रत्येक शब्द को फ़ाइल नामों के मिलान के लिए जांचा जाता है (या जैसा कि यदि वे किसी भी फ़ाइल से मेल नहीं खाते हैं तो छोड़ दिया जाता है), और forउन सभी को लूप करता है।

में for i in "$(xrandr)", हम स्प्लिट + ग्लोब ऑपरेटर का उपयोग नहीं कर रहे हैं क्योंकि कमांड प्रतिस्थापन को उद्धृत किया गया है, इसलिए एक मूल्य पर लूप में एक पास है : आउटपुट आउटपुट xrandr(अनुवर्ती न्यूलाइन वर्ण के बिना जो प्रतिस्थापन स्ट्रिप्स को कमांड करता है )।

हालाँकि echo $i, $iफिर से अयोग्य करार दिया जाता है, इसलिए फिर से सामग्री $iको विभाजित किया जाता है और फ़ाइलनाम पीढ़ी के अधीन होता है और उन्हें echoकमांड के अलग-अलग तर्कों के रूप में पारित किया जाता है (और echoरिक्त स्थान द्वारा अलग किए गए इसके तर्कों को आउटपुट करता है)।

तो सबक सीखा:

  • यदि आप शब्द विभाजन या फ़ाइल नाम नहीं चाहते हैं , तो हमेशा चर विस्तार और कमांड प्रतिस्थापन को उद्धृत करें
  • यदि आप शब्द विभाजन या फ़ाइल नाम बनाना चाहते हैं , तो उन्हें बिना पढ़े छोड़ दें, लेकिन $IFSतदनुसार सेट करें और / या ज़रूरत पड़ने पर फ़ाइल नाम पीढ़ी को सक्षम या अक्षम करें ( set -f, set +f)।

आमतौर पर, ऊपर दिए गए उदाहरण में, यदि आप आउटपुट में शब्दों की रिक्त पृथक सूची पर लूप करना चाहते हैं, तो आपको xrandrनिम्न की आवश्यकता होगी:

  • $IFSरिक्त स्थान पर विभाजित करने के लिए इसके डिफ़ॉल्ट मान (या इसे अनसेट) पर छोड़ दें
  • उपयोग set -fअक्षम फ़ाइल नाम पीढ़ी के लिए जब तक आप सुनिश्चित हैं कि xrandrकिसी भी आउटपुट कभी नहीं *या ?या [वर्ण (जो वाइल्डकार्ड फ़ाइल नाम पीढ़ी पैटर्न में किया जाता है)

और फिर लूप के inहिस्से में केवल स्प्लिट + ग्लोब ऑपरेटर (केवल कमांड कमांड प्रतिस्थापन या वेरिएबल एक्सपेंशन छोड़ें) का उपयोग करें for:

set -f; unset -v IFS
for i in $(xrandr); do whatever with "$i"; done

आप (गैर खाली) पर पाश चाहते हैं लाइनों का xrandrउत्पादन, आप सेट करना होगा $IFSन्यू लाइन चरित्र के लिए:

IFS='
'

4

एक उद्धृत न्यूलाइन एक न्यूलाइन है। इसलिए echo "$1"एकल कमांड लाइन को प्रतिध्वनित करने के लिए तर्क देता है, जो तब सीधे नईलाइन्स को प्रिंट करता है।

एक निर्विवाद न्यूलाइन व्हॉट्सएप है। तो echo $1प्रतिध्वनि के लिए कई कमांड लाइन तर्क देता है, जो रिक्त स्थान के साथ एक के बाद एक उन्हें प्रिंट करता है।


एक अनछुई न्यूलाइन है व्हॉट्सएप वास्तव में उपयोगी होने के लिए एक शॉर्ट-कट का बहुत अधिक हिस्सा है, यहां आईएमओ के व्यवहार की व्याख्या के रूप में उपयोगी है।
स्टीफन चेज़लस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.