[[$ A == z *] और [$ a == z *] के बीच क्या अंतर है?


35

क्या इन दोनों में कोई अंतर है

[[ $a == z* ]]

तथा

[ $a == z* ] 

क्या मेरे पास एक उदाहरण हो सकता है जहां उनके पास अलग-अलग आउटपुट होंगे?

इसके अलावा, कैसे काम करता [[ ]]है से अलग है [ ]?

जवाबों:


41

के बीच का अंतर [[ … ]]और [ … ]ज्यादातर सिंगल या डबल ब्रैकेट का उपयोग करके कवर किया जाता है - बैश । महत्वपूर्ण रूप से, [[ … ]]विशेष वाक्यविन्यास है, जबकि [एक कमांड के लिए एक मजाकिया दिखने वाला नाम है। [[ … ]]अंदर क्या है, [ … ]इसके लिए विशेष वाक्यविन्यास नियम नहीं हैं।

वाइल्डकार्ड की अतिरिक्त शिकन के साथ, यहाँ कैसे [[ $a == z* ]]मूल्यांकन किया गया है:

  1. कमांड को पार्स करें: यह [[ … ]]सशर्त अभिव्यक्ति के चारों ओर सशर्त निर्माण है $a == z*
  2. सशर्त अभिव्यक्ति को पार्स करें: यह ==बाइनरी ऑपरेटर है, ऑपरेंड्स के साथ $aऔर z*
  3. चर के मान में पहले ऑपरेंड का विस्तार करें a
  4. ==ऑपरेटर का मूल्यांकन करें : परीक्षण करें यदि चर का मान aपैटर्न से मेल खाता है z*
  5. सशर्त अभिव्यक्ति का मूल्यांकन करें: इसका परिणाम सशर्त ऑपरेटर का परिणाम है।
  6. कमांड का अब मूल्यांकन किया जाता है, इसकी स्थिति 0 है यदि सशर्त अभिव्यक्ति सही थी और 1 यदि यह गलत था।

[ $a == z* ]इसका मूल्यांकन कैसे किया जाता है:

  1. आदेश पार्स करें: यह है [तर्क शब्द का मूल्यांकन द्वारा गठित साथ आदेश $a, ==, z*, ]
  2. $aचर के मान में विस्तार करें a
  3. कमांड के मापदंडों पर शब्द विभाजन और फ़ाइल नाम का प्रदर्शन करें।
    • उदाहरण के लिए, यदि का मूल्य a6-चरित्र स्ट्रिंग है foo b*(उदाहरण के द्वारा प्राप्त a='foo b*') और वर्तमान निर्देशिका है (में फ़ाइलों की सूची bar, baz, qux, zim, zum), तो विस्तार का परिणाम शब्द के निम्नलिखित सूची है: [, foo, bar, baz, ==, zim, zum, ]
  4. [पिछले चरण में प्राप्त मापदंडों के साथ कमांड चलाएं ।
    • ऊपर दिए गए उदाहरण मूल्यों के साथ, [कमांड एक सिंटैक्स त्रुटि की शिकायत करता है और स्थिति 2 लौटाता है।

नोट: [[ $a == z* ]]चरण 3 में, मान का aविभाजन और फ़ाइल नाम का निर्माण नहीं होता है, क्योंकि यह एक ऐसे संदर्भ में है जहाँ एक शब्द की अपेक्षा की जाती है (सशर्त ऑपरेटर के बाएं हाथ का तर्क ==)। ज्यादातर मामलों में, यदि कोई शब्द उस स्थिति में समझ में आता है, तो चर विस्तार ऐसा व्यवहार करता है जैसे वह दोहरे उद्धरणों में करता है। हालाँकि, उस नियम का एक अपवाद है: [[ abc == $a ]]यदि aवाइल्डकार्ड में मान समाहित है, तो aवाइल्डकार्ड पैटर्न से मिलान किया जाता है। उदाहरण के लिए, यदि मान aहै a*तो [[ abc == $a ]]सच है (क्योंकि मैचों *के निर्विवाद विस्तार से आने वाला वाइल्डकार्ड ) गलत है (क्योंकि साधारण चरित्र है)$a*[[ abc == "$a" ]]*के उद्धृत विस्तार से $aमेल नहीं खाता bc)। अंदर [[ … ]], डबल कोट कोई फर्क नहीं है, स्ट्रिंग मिलान ऑपरेटरों के दाएँ हाथ की ओर पर छोड़कर ( =, ==, !=और =~)।


39

[testकमांड के लिए एक उपनाम है । यूनिक्स संस्करण 6 में एक ifकमांड था, लेकिन वर्जन 7 (1979) नए बॉर्न शेल के साथ आया, जिसमें कुछ प्रोग्रामिंग कंस्ट्रक्शन थे, जिनमें अगर-तब-और-एलिफ-फाई कंस्ट्रक्शन भी शामिल था, और यूनिक्स वर्जन 7 में एक testकमांड जोड़ा गया था, जो ज्यादातर काम करता था "परीक्षण" जो ifपुराने संस्करणों में कमांड द्वारा किए गए थे ।

[को एक उर्फ ​​बनाया गया था testऔर दोनों को यूनिक्स सिस्टम III (1981) में शेल में बनाया गया था । हालांकि यह ध्यान दिया जाना चाहिए कि कुछ यूनिक्स वेरिएंट के पास [बहुत बाद तक एक कमांड नहीं थी ( 2000 के दशक के शुरुआती दिनों तक कुछ बीएसडी पर जहां shअल्मक्विस्ट शेल पर आधारित है (एक बेसिनtest हमेशा ash's स्रोत में शामिल किया गया है , लेकिन उन पर) बीएसडी (यह शुरुआत में अक्षम था))।

ध्यान दें कि testउर्फ ["परीक्षण" करने के लिए एक कमांड है, कोई भी असाइनमेंट नहीं है जो कि कमांड करता है, इसलिए एक असाइनमेंट और समानता ऑपरेटर के बीच अंतर करने का कोई कारण नहीं है, इसलिए समानता ऑपरेटर है ===केवल कुछ हालिया कार्यान्वयनों द्वारा समर्थित है [(और इसके लिए केवल एक उपनाम है =)।

क्योंकि [एक कमांड से ज्यादा कुछ नहीं है, इसे उसी तरह से पार्स किया जाता है जैसे शेल द्वारा किसी अन्य कमांड को।

विशेष रूप से, आपके उदाहरण में $a, क्योंकि इसे उद्धृत नहीं किया गया है, शब्द विभाजन के सामान्य नियमों के अनुसार कई शब्दों में विभाजित किया जाएगा, और प्रत्येक शब्द फ़ाइलनाम पीढ़ी उर्फ ​​ग्लोबिंग से गुजरना होगा जिसके परिणामस्वरूप संभवतः अधिक शब्द होंगे, उनमें से प्रत्येक शब्द जिसके परिणामस्वरूप था [कमांड के लिए एक अलग तर्क ।

इसी तरह, z*वर्तमान निर्देशिका में फ़ाइल नाम की सूची के साथ विस्तारित किया जाएगा z

तो उदाहरण के लिए, अगर $aहै b* = x, और देखते हैं z1, z2, b1और b2वर्तमान निर्देशिका में फ़ाइलों को, [आदेश 9 तर्क मिलेगा: [, b1, b2, =, x, ==, z1, z2और ]

[एक सशर्त अभिव्यक्ति के रूप में अपने तर्कों को पार्स करता है। वे 9 तर्क एक वैध सशर्त अभिव्यक्ति तक नहीं जोड़ते हैं, इसलिए यह संभवतः एक त्रुटि लौटाएगा।

[[ ... ]]निर्माण कॉर्न खोल द्वारा पेश किया गया था शायद आसपास 1988 ksh86aसे 1987 में यह नहीं था, जबकि ksh88यह शुरू से ही था।

बगल में ksh (सभी कार्यान्वयन), [[...]]भी bash (संस्करण 2.02 के बाद से) और zsh द्वारा समर्थित है, लेकिन सभी तीन कार्यान्वयन अलग-अलग हैं और एक ही शेल के प्रत्येक संस्करण के बीच अंतर हैं, हालांकि परिवर्तन आम तौर पर पिछड़े संगत हैं (एक उल्लेखनीय है जो बैश है) =~ऑपरेटर जो एक निश्चित संस्करण के बाद कुछ लिपियों को तोड़ने के लिए जाना जाता है जब इसका व्यवहार बदल जाता है)। [[...]]POSIX, या Unix या Linux (LSB) द्वारा निर्दिष्ट नहीं है। इसे कुछ बार शामिल करने पर विचार किया गया है, लेकिन इसे शामिल नहीं किया गया है क्योंकि प्रमुख शेल द्वारा समर्थित इसकी सामान्य कार्यक्षमता पहले से ही [कमांड और case-in-esacनिर्माण द्वारा कवर की गई है ।

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

[[ ... ]]==शुरू से जानता है और =1 के बराबर है । Ksh का एक गलती है, हालांकि है (और भ्रम और कई कीड़े खड़ी कर रहा है) है कि =और ==एक समानता ऑपरेटर लेकिन एक पैटर्न मिलान ऑपरेटर (हालांकि नहीं कर रहे हैं मिलान पहलू के हवाले से साथ लेकिन यह स्पष्ट नहीं कि नियमों खोल करने के लिए खोल से अलग से निष्क्रिय किया जा सकता)।

आपके कोड के ऊपर [[ $a == z* ]], शेल सामान्य लोगों के समान नियमों में कई टोकन में पार्स करेगा, इसे एक पैटर्न मिलान तुलना के रूप में पहचानता है, चर z*की सामग्री के खिलाफ मिलान करने के लिए एक पैटर्न के रूप में aमानता है।

आम तौर पर, अपने आप को पैर में गोली मारना कठिन [[ ... ]]होता है क्योंकि यह [कमांड के साथ होता है । लेकिन कुछ नियम जैसे

  • हमेशा चर बोलते हैं
  • -aया -oऑपरेटर का उपयोग कभी न करें (कई [कमांड &&और || शेल ऑपरेटर का उपयोग करें)

[POSIX गोले के साथ विश्वसनीय बनाओ ।

[[...]]अलग-अलग गोले में अतिरिक्त संचालकों का समर्थन करते हैं -nt, जैसे कि रेग्जिप मिलान ऑपरेटरों ... लेकिन सूची और व्यवहार शेल से शेल और संस्करण से भिन्न होता है।

इसलिए जब तक आप यह नहीं जानते कि आपकी स्क्रिप्ट किस शेल और न्यूनतम संस्करण की व्याख्या करेगी, तो यह शायद मानक [कमांड के साथ रहना सुरक्षित है ।


1 एक अपवाद: [[...]]संस्करण में बैश करने के लिए जोड़ा गया था 2.02। जब तक 2.03इसे बदल दिया गया था, तब तक यह [[ x = '?' ]]सच [[ x == '?' ]]होगा जबकि झूठे वापस आ जाएगा। यह उद्धृत करना है कि =उन संस्करणों में ऑपरेटर का उपयोग करते समय पैटर्न मिलान को रोकना नहीं था , लेकिन उपयोग करते समय किया ==


बढ़िया जानकारी। क्या आप कृपया बताएंगे कि "-a या -o ऑपरेटर का उपयोग क्यों नहीं करें"?
grebneke

@grebneke, कोशिश [ '!' = foo -o a = a ]में bashउदाहरण के लिए।
स्टीफन चेज़लस

0

दोनों का उपयोग अभिव्यक्तियों के मूल्यांकन के लिए किया जाता है और [[POSIX पुराने बोर्न शेल के साथ काम नहीं करेगा और [[पैटर्न मिलान और रेगेक्स का भी समर्थन करता है। उदाहरण इनका प्रयास करें

[ $n -eq 0 -a $y -eq 0 ] && echo "Error" || echo "Ok"

[[ $n -eq 0 && $y -eq 0 ]] && echo "Error" || echo "Ok"


ध्यान दें कि बॉर्न शेल POSIX नहीं है, [[...]]केवल कुछ गोले के कुछ संस्करणों में regexps का समर्थन करता है, जैसे कुछ संस्करण [regexp मिलान का समर्थन करते हैं। गणितज्ञ तुलना के लिए, उन गोले में जो समर्थन करते हैं [[, आप बल्कि लिखेंगे(( n == 0 && y == 0))
स्टीफन चेज़लस
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.