Ksh में "[[" और "-e xxx" के बीच रिक्त स्थान क्यों आवश्यक है?


9

उदाहरण के लिए, निम्न कमांड काम नहीं करता है:

if [[-e xyz]]; then echo File exists;fi

ksh निम्नलिखित त्रुटि देता है

[[-e: command not found

क्या इसलिए कि "[[-" अस्पष्ट है?


2
[[एक कीवर्ड है - संभवतः शेल के पार्स ट्री के लिए आवश्यक है कि कीवर्ड को
व्हॉट्सएप

इसे देखने का एक और तरीका यह है कि आप एक फ़ंक्शन लिख सकते हैं [[-, शेल को पार्स करने के लिए कैसे पता चलेगा "" ई फंक्शन के बजाय "[ई - ऑन" फंक्शन [[- ई।
pbhj

जवाबों:


15

सबसे सरल स्पष्टीकरण होगा, क्योंकि मैनुअल में ऐसा प्रतीत होता है जैसे [[ expression ]]कि [[और बीच expressionऔर बंद होने के लिए जगह होनी चाहिए ]]। लेकिन निश्चित रूप से हम इसे और गहराई से देखने का प्रयास कर सकते हैं। शेल में कुछ जटिल व्याकरण होते हैं और "शब्द विभाजन" की अवधारणा पर बहुत अधिक भरोसा करते हैं। विशेष रूप से, ksh (1) मैनुअल स्टेट्स:

खोल अपने इनपुट को शब्दों में तोड़कर पार्स करना शुरू कर देता है। शब्द, जो वर्णों के अनुक्रम हैं, को निर्विवाद श्वेत-स्थान वाले वर्णों (स्थान, टैब और न्यूलाइन) या मेटा-वर्णों (<,>,;,;, और (और)) द्वारा सीमांकित किया जाता है। परिसीमन शब्दों के अलावा, रिक्त स्थान और टैब को नजरअंदाज कर दिया जाता है, जबकि नए सिरे आमतौर पर आदेशों का परिसीमन करते हैं।

इसलिए जैसा कि नियमावली में कहा गया है, वर्णों के अनुक्रम को [[-eएक शब्द शब्द माना जाता है। kshबिल्ट-इन और विशेष ऑपरेटरों (जैसे forया while) की सूची में इस तरह के कमांड की तलाश करेंगे , फिर एक बाहरी कमांड की तलाश करेंगे - और वॉइलिया - कोई नहीं मिला, इसलिए कमांड के बारे में कोई त्रुटि संदेश नहीं मिला।

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

कंपाउंड कमांड निम्न आरक्षित शब्दों का उपयोग करके बनाई गई हैं - इन शब्दों को केवल तभी पहचाना जाता है यदि वे अयोग्य हैं और यदि उन्हें कमांड के पहले शब्द के रूप में उपयोग किया जाता है (यानी, वे पैरामीटर असाइनमेंट या पुनर्निर्देशन से पहले नहीं हो सकते हैं):

इसलिए [[कंपाउंड कमांड के रूप में पहचाने जाने के लिए , इसे कमांड या कमांड लिस्ट का पहला शब्द होना चाहिए, जो "शब्द" की पिछली परिभाषा से तात्पर्य है कि इसे स्पेस, टैब या अन्य से अलग करना होगा। शब्द / तर्क।


आपने टिप्पणियों में पूछा है : "" [["पैटर्न मिलते ही पार्सर क्यों नहीं रुक सकता, और यह मानते हैं कि सशर्त कमांड की शुरुआत के रूप में?" संक्षिप्त उत्तर शायद इसलिए है क्योंकि 1) [सिंटैक्स का प्रभाव क्योंकि यह मूल रूप से एक बाहरी कमांड था, और POSIX मानक अनुपालन के लिए आज भी बाहरी कमांड के रूप में मौजूद है, और 2) क्योंकि शेल पार्सर बनाया गया है। शेल पार्सर अन्य गैर-स्थान सीमांकित विशेष वर्णों को पहचान सकता है: echo $((2+2))और (echo foobar)पूरी तरह से ठीक काम करता है। हो सकता है कि भविष्य में जब kshविकास फिर से शुरू हो या कोई कांटा या क्लोन (जैसे mkshया pdksh) प्रतीत हो, तो कोई अंतरिक्ष में कम-से-कम सिंटैक्स लागू करेगा [[-e

यह सभी देखें:


3
मुझे लगता है कि ksh मैनुअल बोली वास्तव में मौके पर है। यह किसी भी अन्य प्रोग्रामिंग भाषा के समान है: C में, charएक कीवर्ड है लेकिन आप अभी भी लिख नहीं सकते हैं charsomeletter = 'A';और पार्सर को देखने के बाद बंद होने की उम्मीद कर सकते हैं char
पीटर -

मुझे लगता है कि "चार" और प्रतीक के आपके उदाहरण के बीच मुख्य अंतर "[[" प्रश्न में है कि, एक अल्फ़ान्यूमेरिक पहचानकर्ता, सामान्य रूप से, दूसरों से अलग होने के लिए अंतरिक्ष सीमांकक की आवश्यकता है; दूसरी ओर, टोकन के रूप में विशेष प्रतीकों को अंतरिक्ष में सीमांकक की आवश्यकता नहीं है।
अकबप

बिल्कुल सही। मुझे यकीन नहीं है कि सी की तुलना सहायक है। सी में एक कह सकते हैं i--<=++j, और संकलक के रूप में पार्स करने में कोई समस्या नहीं है i -- <= ++ j
स्कॉट

@ मुझे लगता है कि सी तुलना सहायक है (और यह माध्यमिक की तरह है कि सी पहचानकर्ता केवल अल्फ़ान्यूमेरिक्स और _) की अनुमति देते हैं । Ksh के पास (एक ऑपरेटर के रूप में है , और (echo hello)पर्स के रूप में ( echo hello )। यह है if, {, [[, और अन्य कीवर्ड , और ifx, {xऔर [[xहर एक टोकन कर रहे हैं - कैसे की तरह charsomeletterएक सी टोकन है। इसके विपरीत, (xksh में एक अयोग्य दो टोकन हैं - जैसे कि i--C. में दो टोकन कैसे हैं । वैचारिक रूप से इसका अर्थ यह भी है कि ऑपरेटर का बॉर्न-शैली के गोले (जैसे ksh) और C. के बीच अंतर होता है, लेकिन पीटर ए। श्नाइडर ने बताया वास्तविक शाब्दिक समानता।
एलिया कागन

2

यह नोट करना महत्वपूर्ण है कि [एक कमांड क्या है , और [[bash और ksh में शेल कीवर्ड पर आधारित है [

[[के लिए एक समान तरीके से उपयोग किया जाता है [कभी-कभी आप व्यवहार में कोई बदलाव न करने के [ ]साथ भी बदल सकते [[ ]]हैं। [किसी भी आदेश के साथ , कमांड और उसके तर्कों के बीच एक स्थान अनिवार्य है। वही लागू होता है [[

हमारे पास ही हुआ करती थी /usr/bin/[। अब अधिकांश गोले [दक्षता के लिए बनाए गए हैं - लेकिन सिंटैक्स समान है। प्रदान करने वाले गोले में [[, यह एक अधिक बहुमुखी विकल्प के रूप में कार्य करता है [

यहाँ [बैश में वर्णन है :

$ help [
[: [ arg... ]
    Evaluate conditional expression.

    This is a synonym for the "test" builtin, but the last argument must
    be a literal `]', to match the opening `['.

के [बराबर है test( ]बहुत अंत में एक तर्क की उम्मीद से अलग )। help testउस पर और भी अधिक विवरण देंगे। आप इसकी तुलना कर सकते हैं help [[

बाहरी कमांड के लिए एक मैन पेज भी है [( man \[)।

के मामले में

if [[-e
  • न तो [है और न ही [[कोई आदेश, वहाँ है। पूरा शब्द [[-eहै।
  • यह if [[-eइसे सत्य / असत्य की परीक्षा बनाता है। तो क्या एक कमांड [[-eमौजूद है?

क्या इसलिए कि "[[-" अस्पष्ट है?

हाँ। याँ नहीं। [[-eयह क्या है: कुछ भी नहीं है कि शेल समझ में आता है तो यह मानता है कि यह अपना आदेश है। ;-)


"% मदद [[" कहता है कि "[[" एक सशर्त आदेश है। जैसे ही यह "[[" पैटर्न पाता है, तो पार्सर क्यों नहीं रोक सकता है और इसे सशर्त कमांड की शुरुआत के रूप में मानता है?
AcBap

@Myloti [[-eएक संभावित वैध (यदि अजीब दिखने वाला) कमांड नाम है।
गॉर्डन डेविसन

2

अंतरिक्ष एक अपराधी है और आवश्यक है। जैसा कि आप देख सकते हैं shellcheck:

$ shellcheck gmail-browse-msgs-algorithm.sh

In gmail-browse-msgs-algorithm.sh line 847:
        [[$Today != "${DaysArr[ i + DAY_DELETED_ON_NDX ]}" ]] && continue
          ^-- SC1035: You need a space after the [[ and before the ]].

(Ksh और bash दोनों समर्थन करते हैं [[और बिना स्पेस के काम नहीं करते। शेल्चेक बिल्कुल उसी ksh और bash स्क्रिप्ट के साथ आउटपुट देता है, जिसमें छोटी गाड़ी लाइन होती है।)

क्यों अपराधियों की जरूरत है टोकन और lexicons के साथ क्या करना है ।


कृपया ध्यान दें, ओपी ने kshप्रश्न में शेल के बारे में पूछा। बैश उधार लेता [[से ऑपरेटर kshऔर इस सवाल का उनके व्यवहार के समान है, लेकिन वहाँ के रूप में के बीच कुछ महत्वपूर्ण अंतर है मैं मान्यताओं के सावधान रहना होगा kshऔर bashव्यवहार और आंतरिक। यह सिर्फ इसलिए है क्योंकि शेलचेक बैश स्क्रिप्ट पर काम करता है, यह आवश्यक रूप से ksh स्क्रिप्ट के लिए उपयुक्त उपकरण नहीं हो सकता है। अलग-अलग गोले के पास जाने के लिए बस कुछ ध्यान में रखें
सर्गीय कोलोडियाज़नी

@SergiyKolodyazhnyy मैं [[अंतर्निहित नियमों को उजागर करने के लिए कवच का उपयोग करके अवसरवादी हो रहा था । मैं किसी भी तरह से जिक्र नहीं कर रहा था कि kshएक शेल था जो shellcheckत्रुटियों को पा सकता था। मुझे आशा है कि अन्य लोग सराहना करते हैं kshऔर bashदो अलग-अलग व्याख्याकार हैं। उस उल्लेख के लिए धन्यवाद। यह भी ध्यान देने योग्य [[है [कि एक बाहरी कमांड में बनाया गया एक बैश है।
विनयुनुच्स 2 यूनिक्स 2

असल [में यह बिल्ट-इन bash :) manpages.ubuntu.com/manpages/bionic/man7/bash-builtins.7.html भी है, लेकिन आप बहुत दूर नहीं हैं - [या testबाहरी कमांड होना आवश्यक है। मूल बॉर्न शेल के दिनों [में वास्तव में एक बाहरी आदेश था, और अभी भी आजकल के रूप में मौजूद है /usr/bin/[क्योंकि POSIX को बाहरी कमांड pubs.opengroup.org/onlinepubs/009695399/utilities/test.html की आवश्यकता होती है क्योंकि कुछ POSIX द्वारा आवश्यक हैं। में निर्मित किया जा pubs.opengroup.org/onlinepubs/009695399/idx/sbi.html अंतर्निहित [क्षमता के लिए है
सर्गी Kolodyazhnyy

2
शेलचेक जानता है ksh; हैशबैंग का उपयोग करें या -s ksh। Btw, ksh और bash में [["बिल्ट इन" है, लेकिन यह एक कीवर्ड है , इसके विपरीत [, जो एक शेल बिलिन है । (ksh whence -v [ [[:; bash type [ [[:) बिल्ट और एक्सटर्नल कमांड सिंटैक्टिक रूप से एक जैसे होते हैं। [[इससे अलग एक तरीका यह [है कि वह [[अपने तर्कों में कुछ विस्तार को दबाता है, जो कि वह बिलियन के रूप में {नहीं कर सकता है - जितना समूहन नहीं कर सकता था वह एक बिलिन था। यह हो सकता है क्यों {x(या [[x) एक टोकन अजीब लग रहा है। मुझे लगता है कि यह कहना सही है कि बिलिन और कीवर्ड लेक्सिक हैं, लेकिन सिंटैक्टिक रूप से समान नहीं हैं । @SergiyKolodyazhnyy
कागन

1
@EliahKagan वास्तव में, मैंने U & L पर एक प्रश्न पोस्ट किया है, जो इस स्थिति के बारे में POSIX के बारे में एक सटीक जवाब पाने के लिए unix.stackexchange.com/questions/526574/… शैल भाषा पर्याप्त जटिल है, इसलिए उम्मीद है कि कोई व्यक्ति इसे और अधिक औपचारिक शब्दों में समझा सकता है।
सर्गी कोलोडाज़नी

1

[[एक बाहरी आदेश हो सकता है! यही है, यह एक कार्यक्रम हो सकता है और सीधे आपके शेल द्वारा समर्थित कुछ सिंटैक्स नहीं। स्पेस-कम सिंटैक्स का समर्थन करना संभव होगा, kshलेकिन यह बाहरी के साथ सिस्टम पर विफल होगा, [[इसलिए अनुकूलता के लिए आवश्यक स्थान रखना बेहतर है।

[[उदाहरण के लिए बिजीबॉक्स एक बाहरी कमांड के रूप में प्रदान कर रहा है


0

चूंकि [[-eशेल विस्तार में भाग ले सकते हैं (इसका उपयोग किया जा सकता है

echo [[-e]*

सभी फ़ाइलों को सूचीबद्ध करने के लिए [और बीच में एक अक्षर के साथ शुरू होने वाली सूची e), यह एक पूर्ण गड़बड़ी होगी यदि [और ]विशेष वर्ण सामान्य व्हाट्सएप-शासित शब्द विभाजन में भाग नहीं ले रहे थे।

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