गूँज के साथ अप्रत्याशित व्यवहार [[: अंक:]]


10

मैं पूछना चाहता हूँ:

echo {1,2,3}1 2 3 का विस्तार क्यों किया गया है, जो एक अपेक्षित व्यवहार है, जबकि echo [[:digit:]]रिटर्न, [[:digit:]]जबकि मुझे उम्मीद थी कि यह सभी अंकों को प्रिंट 0करेगा 9?


: से सावधान रहें unix.stackexchange.com/q/347950/117549
जेफ स्कालर

जवाबों:


34

क्योंकि वे दो अलग चीजें हैं। {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

$ 

4
shopt -s failglobआधुनिक गोले जैसे zshया के समान एक अधिक उपयोगी व्यवहार प्राप्त करने के लिए भी देखें fish
स्टीफन चेजालस

मैं स्टीफन से सहमत हूं, उपयोग करें failglobnullglobएक URL को चिपकाते समय अनपेक्षित समस्याएँ पैदा कर सकता है, जैसे कि ?
केविन

1
निश्चित रूप से, मैंने केवल nullglobयह प्रदर्शित करने के लिए उल्लेख किया है कि पैटर्न को शेल द्वारा ग्लोब के रूप में व्याख्या किया जा रहा है।
terdon

14

{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}

आपके उत्तर के लिए धन्यवाद, लिनक्स में नया हूँ, इसलिए कृपया मुझे आपसे पूछें कि इको फ़ाइलों 1 3 से संबंधित कैसे है, यह फ़ंक्शन है कि मेरे ज्ञान के रूप में फ़ाइलों की खोज न करने के लिए अपने तर्क मुद्रित करना है
अब्दुल्लाह तालात

1
@AbdAllahTalaat का वास्तव में गूंज से कोई लेना-देना नहीं है। शेल (जैसे bash) इसे पास करने से [[:digit:]] पहले "विस्तार" करेगा echo, इसलिए echoकभी नहीं देखता [[:digit:]], यह केवल देखता है 1 3। आप इसे चालू करके देख सकते हैं set -xजो चलाए जा रहे वास्तविक कमांड को प्रिंट करेगा ( set +xइसे फिर से चालू करने के लिए)।
terdon

@AbdAllahTalaat, echoफ़ाइलों को देखने के लिए नहीं है, शेल करता है, चलाने से पहले echo
ilkachachu

खासकर जब से मुझे लगता है कि डॉस / विंडोज में यूटिलिटीज वाइल्डकार्ड का विस्तार करती हैं, शेल का नहीं। (मैं शायद गलत हूं)
ilkachachu

क्षमा करें दोस्तों मैंने सही उत्तर को टेड्रोन के उत्तर में स्थानांतरित कर दिया क्योंकि उनकी टिप्पणी में यह अर्थ था कि बैश वह है जो कार्य को प्रतिध्वनित नहीं करता है ... उनके उत्तर में इसका अर्थ भी था .. आप सभी ने मेरी मदद की ... मैं चाहता था कि मैं डाल सकता था। आपके सभी उत्तरों और टिप्पणियों के लिए सही उत्तर
अब्दुल्लाह तलत

4

{1,2,3}(और जैसे {1..3}हैं ब्रेस विस्तार । वे आदेश निष्पादन से पहले खोल से व्याख्या कर रहे हैं।

[[:digit:]]टोकन से मेल खाने वाला एक पैटर्न है , लेकिन आप इसे किसी भी फाइल के साथ उस स्थान पर उपयोग नहीं कर रहे हैं जो उस पैटर्न से मेल खाता है। यदि आप एक पैटर्न मैच का उपयोग करते हैं जिसका कोई मिलान नहीं है, तो यह अपने आप फैलता है:

$ echo [[:digit:]]; touch 3; echo [[:digit:]]
[[:digit:]]
3

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