मैं पूछना चाहता हूँ:
echo {1,2,3}1 2 3 का विस्तार क्यों किया गया है, जो एक अपेक्षित व्यवहार है, जबकि echo [[:digit:]]रिटर्न, [[:digit:]]जबकि मुझे उम्मीद थी कि यह सभी अंकों को प्रिंट 0करेगा 9?
मैं पूछना चाहता हूँ:
echo {1,2,3}1 2 3 का विस्तार क्यों किया गया है, जो एक अपेक्षित व्यवहार है, जबकि echo [[:digit:]]रिटर्न, [[:digit:]]जबकि मुझे उम्मीद थी कि यह सभी अंकों को प्रिंट 0करेगा 9?
जवाबों:
क्योंकि वे दो अलग चीजें हैं। {1,2,3}का एक उदाहरण है ब्रेस विस्तार । {1,2,3}निर्माण का विस्तार होता है खोल से , इससे पहले echoभी देखता है। यदि आप उपयोग करते हैं तो आप देख सकते हैं कि क्या होता है set -x:
$ set -x
$ echo {1,2,3}
+ echo 1 2 3
1 2 3
जैसा कि आप देख सकते हैं, कमांड echo {1,2,3}का विस्तार किया गया है:
echo 1 2 3
हालाँकि, [[:digit:]]एक POSIX वर्ण वर्ग है । जब आप इसे देते हैं echo, तो शेल पहले इसे संसाधित करता है, लेकिन इस बार इसे शेल ग्लोब के रूप में संसाधित किया जा रहा है । यह उसी तरह काम करता है जैसे कि आप चलाते हैं echo *जो वर्तमान निर्देशिका में सभी फ़ाइलों को प्रिंट करेगा। लेकिन [[:digit:]]एक शेल गोला है जो किसी भी अंक से मेल खाएगा। अब, यदि कोई शेल ग्लोब कुछ भी मेल नहीं खाता है, तो उसे अपने आप में विस्तारित किया जाएगा:
$ echo /this*matches*no*files
+ echo '/this*matches*no*files'
/this*matches*no*files
अगर ग्लोब किसी चीज़ से मेल खाता है, तो वह मुद्रित हो जाएगा:
$ echo /e*c
+ echo /etc
/etc
दोनों मामलों में, echoजो कुछ भी खोल को प्रिंट करने के लिए कहता है, उसे प्रिंट करता है, लेकिन दूसरे मामले में, चूंकि ग्लोब कुछ से मेल खाता है ( /etc) यह बताया जाता है कि वह कुछ प्रिंट करता है।
इसलिए, चूंकि आपके पास ऐसी कोई फ़ाइल या निर्देशिका नहीं है, जिनके नाम में एक अंक (जो [[:digit:]]मेल खाएगा), ग्लोब का विस्तार अपने आप होता है और आपको मिलता है:
$ echo [[:digit:]]
[[:digit:]]
अब, एक फ़ाइल बनाने का प्रयास करें जिसे एक 5ही कमांड कहा जाता है और चल रहा है:
$ echo [[:digit:]]
5
और अगर एक से अधिक मिलान फ़ाइलें हैं:
$ touch 1 5
$ echo [[:digit:]]
1 5
यह इस व्यवहार को बंद man bashकरने वाले nullglobविकल्पों की व्याख्या में प्रलेखित (क्रमबद्ध) है:
nullglob
If set, bash allows patterns which match no files (see
Pathname Expansion above) to expand to a null string,
rather than themselves.
यदि आप यह विकल्प सेट करते हैं:
$ rm 1 5
$ shopt -s nullglob
$ echo [[:digit:]] ## prints nothing
$
shopt -s failglobआधुनिक गोले जैसे zshया के समान एक अधिक उपयोगी व्यवहार प्राप्त करने के लिए भी देखें fish।
failglob। nullglobएक URL को चिपकाते समय अनपेक्षित समस्याएँ पैदा कर सकता है, जैसे कि ?।
nullglobयह प्रदर्शित करने के लिए उल्लेख किया है कि पैटर्न को शेल द्वारा ग्लोब के रूप में व्याख्या किया जा रहा है।
{1,2,3}है ब्रेस विस्तार है, यह उनके अर्थ के संबंध के बिना सूचीबद्ध शब्दों को विस्तृत करता है।
[...]एक वर्ण समूह है, जिसका उपयोग फ़ाइल नाम विस्तार (या वाइल्डकार्ड, या ग्लोब) में तारांकन *और प्रश्न चिह्न के समान किया जाता है ?। यह भीतर सूचीबद्ध किसी भी एकल वर्ण से मेल खाता है, या वर्ण जो नामित समूहों के सदस्य हैं जैसे [:digit:]कि वे सूचीबद्ध हैं। अधिकांश गोले का डिफ़ॉल्ट व्यवहार वाइल्डकार्ड को छोड़ना है-जैसे कि कोई फ़ाइल नहीं है जो इसे मेल खाते हैं।
(ध्यान दें कि आप वास्तव में एक वाइल्डकार्ड / पैटर्न को स्ट्रिंग्स के सेट में बदल नहीं सकते हैं जो कि मेल खाएगा। तारांकन किसी भी लंबाई के किसी भी तार से मेल खा सकता है, इसलिए किसी भी पैटर्न का विस्तार करने से यह तार की अनंत सूची का उत्पादन करेगा।)
इसलिए:
$ bash -c 'echo [[:digit:]]' # bash leaves it as-is
[[:digit:]]
$ zsh -c 'echo [[:digit:]]' # zsh by default complains if no match
zsh:1: no matches found: [[:digit:]]
$ touch 1 3 d i g t
$ bash -c 'echo [[:digit:]]' # now there are two matches
1 3 # note that d, i, g and t do NOT match
फिर भी:
$ bash -c 'echo {1,2,3}'
1 2 3
उन दोनों को शेल द्वारा विस्तारित किया जाता है , इससे कोई फर्क नहीं पड़ता कि आप जो कमांड चला रहे हैं वह है ls, या echoया rm। यह भी ध्यान दें कि यदि उनमें से कोई भी उद्धृत किया गया है, तो उनका विस्तार नहीं किया जाएगा:
$ bash -c 'echo "[[:digit:]]"' # even though matching files still exist
[[:digit:]]
$ bash -c 'echo "{1,2,3}"'
{1,2,3}
[[:digit:]] पहले "विस्तार" करेगा echo, इसलिए echoकभी नहीं देखता [[:digit:]], यह केवल देखता है 1 3। आप इसे चालू करके देख सकते हैं set -xजो चलाए जा रहे वास्तविक कमांड को प्रिंट करेगा ( set +xइसे फिर से चालू करने के लिए)।
echoफ़ाइलों को देखने के लिए नहीं है, शेल करता है, चलाने से पहले echo।
{1,2,3}(और जैसे {1..3}हैं ब्रेस विस्तार । वे आदेश निष्पादन से पहले खोल से व्याख्या कर रहे हैं।
[[:digit:]]टोकन से मेल खाने वाला एक पैटर्न है , लेकिन आप इसे किसी भी फाइल के साथ उस स्थान पर उपयोग नहीं कर रहे हैं जो उस पैटर्न से मेल खाता है। यदि आप एक पैटर्न मैच का उपयोग करते हैं जिसका कोई मिलान नहीं है, तो यह अपने आप फैलता है:
$ echo [[:digit:]]; touch 3; echo [[:digit:]]
[[:digit:]]
3