बैश ग्लोबिंग का इतिहास


11

क्या कोई ऐतिहासिक कारण है कि बैश "ग्लोबिंग" और नियमित अभिव्यक्ति समान नहीं हैं? उदाहरण के लिए, मेरा मानना ​​है कि बैश में [1-2]*कुछ भी मेल खाता है जो 1 या 2 के साथ शुरू होता है और उसके बाद कुछ भी होता है, जबकि एक नियमित अभिव्यक्ति [1-2]*केवल 1s और 2s के अनुक्रम से मेल खाती है। मेरी बैश स्क्रिप्टिंग और REGEX फू दोनों बहुत कमजोर हैं और मैं नियमित रूप से इन मतभेदों से जुड़ी समस्याओं में भागता हूं, जो मुझे उत्सुक बनाता था कि वे अलग क्यों हैं।


3
क्या आप rm -- ^[^.].*\.txt$इसके बजाय करने पर विचार करेंगे rm -- *.txt?
स्टीफन चेजालस

1
अपने क्यू के की ज्यादातर LWN से इस सूत्र में पर छुआ कर रहे हैं: lwn.net/Articles/96687
SLM

ऐसे आदेश हैं जो फ़ाइल नाम पर कार्य करते हैं और regexp लेते हैं। उदाहरण के लिए find . -regex ".*\.txt$" | xargs rm --, या renameफ़ाइलों का नाम बदलने के लिए (यह sedफ़ाइल नाम के लिए है), सावधान रहें कि कुछ सिस्टम अलग हैं rename
ctrl-alt-delor

@ श्रीखंड, मेरा ^[^.].*\.txt$ध्यान डॉट फाइलों की अनदेखी को लेकर था। ध्यान दें कि -regexएक GNU एक्सटेंशन है, ksh93 या zsh जैसे कुछ गोले अपने ग्लब्स में रीजैक्स को सम्मिलित कर सकते हैं (उदाहरण के लिए प्रयास करें ksh93 -c 'echo ~(E:^[^.].*\.txt$)')
स्टीफन चेज़लस

2
यह बैश मौजूदा अभ्यास का इतनी सावधानी से पालन करता है जबकि अपरिवर्तनीय रूप से असंगत परिवर्तन और एक्सटेंशन से बचना इसकी सबसे बड़ी ताकत है।
ओरमज

जवाबों:


12

bashशुरू में 80 के दशक के अंत में kshcsh / tsh से कुछ संवादात्मक विशेषताओं के साथ आंशिक क्लोन के रूप में डिजाइन किया गया था ।

ग्लोबिंग की उत्पत्ति उन पहले के गोले में पाई जानी है जो इसे बनाता है।

kshखुद बॉर्न शेल का विस्तार है। बॉर्न शेल खुद (1979 में यूनिक्स V7 में पहली बार जारी किया गया था) खरोंच से एक साफ कार्यान्वयन था, लेकिन यह थॉम्पसन शेल (V1 -> V6 के खोल) से पूरी तरह से विदा नहीं हुआ और माशे शेल से सुविधाओं को शामिल किया गया।

विशेष रूप से, कमांड तर्कों को अभी भी खाली करके अलग किया |गया था , अब नया पाइप ऑपरेटर ^था लेकिन फिर भी एक विकल्प के रूप में समर्थित था (और यह भी बताता है कि आप क्यों करते हैं [!a-z]और क्या नहीं [^a-z]), $1अभी भी एक स्क्रिप्ट के लिए पहला तर्क था और बैकस्लैश अभी भी बच चरित्र था । तो कई regexp ऑपरेटर्स ( ^\|$) शेल में अपने स्वयं के एक विशेष अर्थ रखते हैं।

थॉम्पसन शेल ग्लोबिंग के लिए एक बाहरी उपयोगिता पर निर्भर करता था। जब कमांड में shअयोग्य *, [या ?s पाया जाता है , तो यह कमांड को रन करेगा glob

rm *.txt

अंत में चल रहे ग्लोब के रूप में होगा:

["glob", "rm", "*.txt"]

और ग्लोब rmउस पैटर्न से मेल खाती फाइलों की सूची के साथ समाप्त हो जाएगा ।

grep a.\*b *.txt

निम्नानुसार चलेगा glob:

["glob", "grep", "a.\252b", "*.txt"]

*इसके बाद के संस्करण है कि चरित्र पर 8 बिट की स्थापना, रोकने के द्वारा उद्धृत किया गया है globवाइल्डकार्ड के रूप में यह इलाज से। globफिर कॉल करने से पहले उस बिट को हटा देगा grep

रेगेक्स के साथ बराबर करने के लिए, यह होगा:

regexp rm '\.txt$'

या:

regexp rm '^[^.].*\.txt$'

डॉट-फाइल्स को बाहर करने के लिए।

ऑपरेटरों से बचने की जरूरत है क्योंकि वे खोल विशेष पात्रों के रूप में दोगुना करते हैं, यह तथ्य कि ., फ़ाइलनाम में आम एक रेगेक्स ऑपरेटर है, यह शुरुआती के लिए फ़ाइल नाम और जटिल मिलान करने के लिए बहुत उपयुक्त नहीं है। ज्यादातर मामलों में, आपको सभी वाइल्डकार्ड्स की आवश्यकता होती है जो किसी एक ( ?) या किसी भी संख्या ( *) वर्णों को बदल सकते हैं ।

अब, अलग-अलग गोले ने विभिन्न ग्लोबिंग ऑपरेटरों को जोड़ा। आजकल, ksh और zsh ग्लब्स (और कुछ हद तक bash -O extglobजो ksh globs के एक सबसेट को लागू करता है) कार्यात्मक रूप से एक सिंटैक्स के साथ regexps के बराबर होता है जो फ़ाइल नाम और वर्तमान शेल सिंटैक्स के साथ उपयोग करने के लिए कम बोझिल होता है। उदाहरण के लिए, zsh(एक्सटेंडेडग्लोब एक्सटेंशन के साथ), आप कर सकते हैं:

echo a#.txt

अगर आप चाहते हैं (संभावना नहीं) फ़ाइल नामों कि के दृश्यों से मिलकर मैच के लिए aके बाद .txt। की तुलना में आसान echo (^a*\.txt$)(यहां शेल ऑपरेटरों से रेगेक्स ऑपरेटरों को अलग करने के तरीके के रूप में उपयोग किया जाता है जो एक तरह से गोले हो सकते थे जो इससे निपट सकते थे)।

echo (foo|bar|<1-20>).(#i)mpg

Mpg फ़ाइलों (केस असंवेदनशील) के लिए जिसका बेसन foo, बार या 1 से 20 तक एक दशमलव संख्या है ...

ksh93अब अपने ग्लब्स में (हालांकि यह काफी छोटी गाड़ी है) regexps (मूल, विस्तारित, पर्ल-जैसे या "संवर्धित") को भी शामिल कर सकता है और यहां तक ​​कि ग्लोब और regexp ( printf %R, printf %P) के बीच कनवर्ट करने के लिए एक उपकरण भी प्रदान करता है :

echo ~(Ei:.*\.txt)

मैच के लिए (गैर छुपा) txt के साथ फ़ाइलें नियमित अभिव्यक्ति xtended केस मैं nsensitively।


शांत लेखन! आप वास्तव में ~(opt:pat)किसी भी पूंजीकृत विकल्प के लिए उपयोग नहीं कर सकते । हो सकता है print -r -- ~(Ei).*\.txt$। एक पैटर्न के हिस्से के लिए बंद पर एक विकल्प टॉगल करने से बचने के लिए केवल अंदर पैटर्न रखना उपयोगी लगता है। अजीब तरह से आप एक ही ग्लोब के भीतर कई पैटर्न भाषाओं को मिला सकते हैं और मैच कर सकते हैं। ~(Ki)*.~(E)txt$समतुल्य है। (अंत में सब कुछ बस रेगेक्स में परिवर्तित हो जाता है और आंतरिक रूप से रेगाक्स के रेगेक्स इंजन को पारित हो जाता है)।
ओरमज

@ormaaj, ~(Ei:.*\.txt)ksh93 o + जैसे 15 साल पुराने संस्करणों के साथ भी मेरे लिए काम करता है।
स्टीफन चेज़लस

मेरे सहेजे गए परीक्षण बायनेरिज़ में से एक (2014-12-24) के साथ काम करता है, लेकिन मुझे याद है कि इसके साथ मुद्दों में चलना। चीजें हमेशा बेतरतीब ढंग से टूटी हुई थीं और प्रत्येक संस्करण के बीच फिर से तय की गईं जब किश अभी भी व्यावसायिक रूप से विकसित थी। मुझे याद है कि पैटर्न मिलान कोड नाजुक क्षेत्रों में से एक है।
ormaaj

@ormaaj, के बीच एक अंतर है ~(E)xऔर ~(E:x)वह यह है कि बाद वाला एंकर है ( xकेवल मैच पर जबकि पूर्व में कुछ भी होने पर मेल खाता है x), जिस तरह का मुद्दा हो सकता है, जिसमें आप भाग गए थे ( ~(-lr)~(E:x)एंकरिंग को हटाने के लिए, ~(E-lr:x)ऐसा नहीं करेंगे)। किसी भी मामले में, मैं मानता हूं कि यह नवीनतम संस्करण में भी सुंदर बगिया है।
स्टीफन चेज़लस

9

क्लेने द्वारा 1956 में नियमित भाषाओं को पेश किया गया था। सेमिनल पेपर में नियमित अभिव्यक्तियों के लिए पूर्ण आधुनिक अंकन नहीं था, लेकिन इसने "क्लेन स्टार" को पेश किया: A*जिसका अर्थ है "किसी भी संख्या में दोहराव A"। अगले दशक में, कुछ अधिक या कम मानक अधिसूचनाएं उभरीं, विशेष रूप .से एक मनमाना चरित्र के लिए और ?इसका मतलब है कि पिछला चरित्र वैकल्पिक है।

बैश के ग्लोबिंग अंकन उपजी से globआदेश में सभी तरह वापस शुरू की यूनिक्स v1 1971 में समय, ग्लोबिंग एक अलग प्रोग्राम द्वारा किया गया था; बाद में इसे खोल में स्थानांतरित कर दिया गया। प्रारंभिक globआदेश का ?अर्थ "किसी एक वर्ण" से है और "वर्णों के *किसी भी क्रम" से है। मुझे नहीं पता कि पात्रों को क्यों चुना गया; ?बहुत सहज है, और *नियमित रूप से एक से प्रेरित हो सकता है।

ग्लोबिंग का उद्देश्य सामान्य अभिव्यक्तियों के रूप में सामान्य होना नहीं था, और नियमित अभिव्यक्ति उस समय बहुत व्यापक नहीं थीं, इसलिए अवधारणाओं को एकजुट करने के लिए कोई कॉल नहीं था। शुरू से ही, वहाँ वाक्यात्मक असंगतियां थे, के साथ ?, .और *फ़ाइल नाम पैटर्न में और नियमित अभिव्यक्ति में अलग अलग बातें अर्थ।

आधुनिक गोले जैसे बैश ग्लोब पैटर्न पर विस्तार करते हैं, लेकिन यह क्रमिक विकास था जो पिछड़े संगतता को बनाए रखता था। Ksh88 (के 1988 संस्करण कॉर्न खोल ) खोल पैटर्न के लिए एक विस्तारित वाक्य रचना है, जो हमेशा की तरह नियमित अभिव्यक्ति के रूप में ही वाक्य रचना नहीं हो सकता है लेकिन दृढ़ता से यह से प्रेरित था शुरू की: *(PATTERN)की पुनरावृत्ति के किसी भी संख्या का मतलब PATTERN, @(PATTERN1|PATTERN2)मतलब " PATTERN1या PATTERN2", आदि।

यदि आप shopt -s extglobपहले जारी करते हैं, तो bash के आधुनिक संस्करण (2.02 से) ksh88 के विस्तारित पैटर्न का समर्थन करते हैं ।


क्या बैश ने कभी एक्सग्लोब का समर्थन नहीं किया है? जहां तक ​​मुझे मालूम है कि बैश, zsh, और {pd, m} ksh ने शुरुआती दिनों से ही ksh88 मैनुअल में दस्तावेज किए गए सटीक ग्लब्स का समर्थन किया है। आज तक Ksh के पास "विस्तारित" ग्लोब क्वांटिफायर को अक्षम करने का विकल्प भी नहीं है, और ksh93 गुच्छा के केवल एक विस्तार है जो ksh88 के आगे कोई भी एक्सटेंशन नहीं है।
ormaaj

2
@ormaaj Ksh88 ने ग्लब्स को बढ़ाया और extglobविकल्प को 1998 के आसपास कहीं भी 2.02 में पेश किया गया। Zsh ने ksh_globउसी समय के आसपास कहीं 3.1 श्रृंखला में हासिल किया। Zsh के पास स्वयं के कई ग्लोबिंग एक्सटेंशन हैं (कुछ को extended_globविकल्प की आवश्यकता है )।
गाइल्स का SO- बुराई पर रोक '

समझा। तो यह वास्तव में एक विकल्प की आवश्यकता का औचित्य साबित करने के लिए काफी देर हो चुकी थी। (मुझे लगता है कि इन दिनों डिफ़ॉल्ट बंद होना व्यर्थ है लेकिन, दिलचस्प है।)
ormaaj

1
@ormaaj, ध्यान दें कि bashइसके विपरीत ksh, एक्सग्लोब बैश नॉन-पॉसिक्स का अनुपालन करता है क्योंकि यह चर में अक्षम नहीं है। में ksh, var='@(*)'; echo $varवर्तमान dir कि के साथ शुरू में सभी फ़ाइल नाम के लिए विस्तारित @(अंत और में )के रूप में POSIX समय में की आवश्यकता है bash -O extglobयह फ़ाइलें सभी को विस्तृत करता है। (फिर भी, कोई व्यक्ति व्यवहार पर विचार कर सकता है, यहाँ अधिक समझ में आता है (और जब आप चर में पैटर्न चाहते हैं तो ksh व्यवहार काफी दर्द भरा होता है)। यह ग्लोब सिंटैक्स उस (पोसिक्स / बॉर्न संगतता) के कारण बहुत अजीब है। Zsh विस्तारित ग्लब्स के साथ तुलना करें।
स्टीफन चेज़लस

@ स्टीफनचेज़ेलस यह सब सच है, और मुझे पसंद है कि कैसे ksh इसके बारे में कुछ हद तक समझदार है। यह शायद ही कभी खेलने के लिए आता है जब तक कि वास्तव में POSIX के लिए विवश न हो। बेहतर सुविधाओं द्वारा प्रतिस्थापित शब्दों के उच्चारण के लिए लगभग हर उपयोग के साथ, और चर में पैटर्न संग्रहीत करना एक चरम उपद्रव है, वैसे भी जब से आपको IFS खाली करना पड़ता है, हर जगह ब्रेस विस्तार अक्षम करें लेकिन बैश। मुझे लगता है कि संग्रहीत पैटर्न के साथ पूरी तरह से सुरक्षित होना अभी भी असंभव है। इस पुराने पलायन मुद्दे को वास्तव में उदाहरण के लिए हल नहीं किया गया था।
ओरमज

1

ऐतिहासिक कारण: हाँ। संदर्भ:
http://en.wikipedia.org/wiki/Glob_(programming)#Origin

बस विचलन दिखाने के लिए, यहाँ एक अच्छा और आसान उदाहरण है: a*

  • शेल ग्लोबिंग: अर्थ है, पहला चरित्र है aऔर फिर जो कुछ भी (ए, अब, अब्बा ...)
  • regex: अर्थ है, चरित्र का शून्य या अधिक दोहराव a(a, aa, aaa ...)

मैं आसानी से सहमत हूँ कि अर्थ में यह विसंगति नए उपयोगकर्ताओं के लिए बहुत भ्रामक है।

ग्लोबिंग शायद नए लोगों के लिए पकड़ना आसान है, लेकिन यह कम शक्तिशाली निर्माण भी है।

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