अत्यधिक मत वाले वन-लाइनर में नेस्टेड दोहरे उद्धरण


20

StackOverflow उत्तर के साथ> 3.5K वोटों DIRको वर्तमान बैश स्क्रिप्ट की निर्देशिका को असाइन करने के लिए इस एक-लाइनर की सुविधा है :

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

मैं नेस्टेड डबल-कोट्स से हैरान हूं। जहां तक ​​मैं बता सकता हूं, निम्नलिखित अंश दोहरे-उद्धृत हैं:

"$( cd "
"${BASH_SOURCE[0]}"
" && pwd )"

... और =(यानी $( dirnameऔर )) के अधिकार के लिए सब कुछ अयोग्य है। दूसरे शब्दों में, मुझे लगता है कि 2, 4, और 6 वें "वर्ण "क्रमशः 1, 3, और 5 वें वर्णों को "बंद" करते हैं।

मुझे समझ में आया कि डबल-कोट्स "${BASH_SOURCE[0]}"क्या हैं, लेकिन डबल-कोट्स के अन्य दो जोड़े का क्या उद्देश्य है?

यदि, दूसरी ओर (और उच्च वोट स्कोर के बावजूद), ऊपर वाला स्निपेट गलत है, तो इसके मामूली इरादे को हासिल करने का सही तरीका क्या है?

( नाममात्र के इरादे से मेरा मतलब है: निर्देशिका द्वारा लौटाए गए pwdपहले cd-ing के बाद लौटाए गए मान को इकट्ठा dirname "${BASH_SOURCE[0]}"करना, और cdएक-शेल में -ing करना , ताकि $PWDमाता-पिता के खोल अपरिवर्तित रहें)।


1
यह $ (...) की एक विशेषता के कारण है $( here, it's a subshell, but you are writing code as if you were writing it on the "first level" of the shell .... ):।
ओलिवियर दुलक

मैं डॉक इंस्टॉल स्क्रिप्ट की वजह से यहां आया था। डिस्ट्रो का नाम खोजने के लिए:lsb_dist="$(. /etc/os-release && echo "$ID")"; echo "$lsb_dist"
डेविड टोनहोफर

ध्यान दें कि पंक्ति में रिक्त स्थान की आवश्यकता नहीं है: DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"साथ ही काम करता है।
डेविड टोनहोफर

जवाबों:


12

आपकी पहेली सही नहीं है कि कैसे bash(और सामान्य रूप से शेल) इनपुट को पार्स किया जाए। में:

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

सबसे पहले, bashएक लंबे स्ट्रिंग के लिए असाइनमेंट के दाहिने हाथ को पार्स करें $( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )क्योंकि डबल कोट डबल कोट्स के अंदर दिखाई दे सकता है ।

उसके बाद, bashकमांड प्रतिस्थापन को पार्स करना शुरू करें। क्योंकि कोष्ठक को खोलने के लिए खुले कोष्ठक का अनुसरण करने वाले सभी वर्णों का उपयोग कमांड प्रतिस्थापन के अंदर कमांड के निर्माण के लिए किया जाता है, आपको यह मिलेगा:

cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd

शेल उस यौगिक कमांड को पार्स करना जारी रखता है, इसे दो भागों में तोड़ता है:

  • cd "$( dirname "${BASH_SOURCE[0]}" )"
  • लोक निर्माण विभाग

तब के लिए एक ही पार्सिंग नियम लागू करना cd "$( dirname "${BASH_SOURCE[0]}" )", लेकिन इस बार, दोहरे उद्धरण बेमानी नहीं हैं, लेकिन समझ में आता है। वे परिणाम के आधार पर फ़ील्ड विभाजन को रोकते हैं $( dirname "${BASH_SOURCE[0]}" ), और ${BASH_SOURCE[0]}बाहरी विस्तार (बाहरी सबसे दोहरे उद्धरणों के विपरीत, रोकने के लिए चर असाइनमेंट के आरएचएस में आवश्यक नहीं हैंsplit+glob )।


यह नियम सभी POSIX शेल में कमांड प्रतिस्थापन के लिए लागू होता है । POSIX कल्पना के टोकन रिकग्निशन सेक्शन में आप एक और विवरण पहेली पढ़ सकते हैं ।


21

एक बार अंदर हो जाने पर $(...), सभी को खरोंचने से उद्धृत करना शुरू हो जाता है।

दूसरे शब्दों में, "..."और एक दूसरे के भीतर घोंसला$(...) कर सकते हैं । प्रक्रिया प्रतिस्थापन, $(...)में एक या एक से अधिक पूर्ण -उद्धृत स्ट्रिंग्स हो सकते हैं। इसके अलावा, डबल-उद्धृत स्ट्रिंग्स में एक या अधिक पूर्ण प्रक्रिया प्रतिस्थापन हो सकते हैं । लेकिन, वे बीच में नहीं आते। इस प्रकार, एक डबल-कोटेड स्ट्रिंग जो एक प्रक्रिया प्रतिस्थापन के अंदर शुरू होती है, कभी भी इसके बाहर या इसके विपरीत विस्तार नहीं करेगी।

तो, विचार करें:

DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"

भीतर ही भीतर $(...)है:

dirname "${BASH_SOURCE[0]}"

इसके बाद के संस्करण ${BASH_SOURCE[0]}में डबल-उद्धृत किया गया है। दोहरे उद्धरण वाले किसी भी उद्धरण, डबल या सिंगल, $(...)अप्रासंगिक हैं ${BASH_SOURCE[0]}

बाहरी $(...)में शामिल हैं:

cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd

यहाँ, अभिव्यक्ति $( dirname "${BASH_SOURCE[0]}" )दोहरे-उद्धृत है। तथ्य यह है कि बाहरी के बाहर उद्धरण हैं $(...)जब यह अंदर है क्या विचार पर अप्रासंगिक है। यह तथ्य कि भीतर के उद्धरण हैं, $(...)यह भी अप्रासंगिक है।

यहां बताया गया है कि डबल-कोट्स कैसे मेल खाते हैं:

यहां छवि विवरण दर्ज करें


क्या मतलब irrelevant? बाहरी सबसे अधिक कोष्ठक को छोड़कर, अन्य सभी का अपना अर्थ है।
congonglm

4
और, यही कारण है कि आपको बैकटिक्स का उपयोग नहीं करना चाहिए: उद्धरण के नियम अत्यंत अजीब और गैर-सहज हैं।
वाइल्डकार्ड

वाक्य " $(...)तंग को बांधता है "..."" से कोई मतलब नहीं है। वे ऑपरेटर नहीं हैं, और उनके बीच कोई पदानुक्रम नहीं है (अगर वहाँ था तो इसका मतलब यह होगा कि या तो उद्धरण कोष्ठक के अंदर नहीं हो सकते हैं या कोष्ठक उद्धरण के अंदर नहीं हो सकते हैं, लेकिन ऐसा नहीं है)। तकनीकी शब्द वह $(…)और "…"घोंसला है।
गिल्स एसओ- बुराई को रोकें '

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