निरंतरता चरित्र के बाद टिप्पणियों के साथ मल्टी लाइन कमांड को बैश करें


29

विचार करें

echo \ # this is a comment
foo

यह देता है:

$ sh foo.sh
 # this is a comment
foo.sh: line 2: foo: command not found

वेब पर कुछ खोज करने के बाद, मुझे डिजिटल साइट द्वारा बहन साइट स्टैक ओवरफ्लो पर एक समाधान मिला । तो एक कर सकते हैं

echo `: this is a comment` \
foo

या वैकल्पिक रूप से

echo $(: this is a comment) \
foo

हालाँकि, DigitalRoss ने यह नहीं बताया कि ये समाधान क्यों काम करते हैं। मैं एक स्पष्टीकरण की सराहना करता हूँ। उन्होंने एक टिप्पणी के साथ जवाब दिया:

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

लेकिन मुझे पोर्टेबिलिटी की चर्चा सहित अधिक विवरण और संदर्भ चाहिए।

बेशक, अगर किसी के पास अन्य समाधान हैं, तो यह भी अच्छा होगा।

पहले वाला प्रश्न भी देखें कि शेल स्क्रिप्ट में मल्टी-लाइन कमांड कैसे टिप्पणी करें?


नीचे चर्चा से घर संदेश ले लो। `: this is a comment`सिर्फ एक आदेश प्रतिस्थापन है। का उत्पादन : this is a commentकुछ भी नहीं है, और वह जगह में डाल दिया जाता है `: this is a comment`

एक बेहतर विकल्प निम्नलिखित है:

echo `# this is a comment` \
foo

जवाबों:


25

टिप्पणियाँ पहली नई पंक्ति में समाप्त होती हैं ( शेल टोकन पहचान नियम 10 देखें ), निरंतरता रेखाओं की अनुमति के बिना , इसलिए इस कोड fooमें एक अलग कमांड कमांड है:

echo # this is a comment \
foo

आपके पहले प्रस्ताव के अनुसार, बैकस्लैश का पालन नई लाइन द्वारा नहीं किया जाता है, आप केवल स्थान उद्धृत कर रहे हैं: यह इसके बराबर है

echo ' # this is a comment'
foo

$(: this is a comment)कमांड के आउटपुट को प्रतिस्थापित करता है : this is a comment। यदि उस कमांड का आउटपुट खाली है, तो यह प्रभावी रूप से एक लाइन के बीच में एक टिप्पणी डालने का एक बहुत ही भ्रामक तरीका है।

कोई जादू चल रहा है: : एक साधारण आदेश है, बृहदान्त्र उपयोगिता, जो कुछ भी नहीं करता है। बृहदान्त्र उपयोगिता ज्यादातर तब उपयोगी होती है जब शेल सिंटैक्स को एक कमांड की आवश्यकता होती है, लेकिन आपके पास ऐसा कुछ नहीं होता है।

# Sample code to compress files that don't look compressed
case "$1" in
  *.gz|*.tgz|*.bz2|*.zip|*.jar|*.od?) :;; # the file is already compressed
  *) bzip2 -9 "$1";;
esac

एक अन्य उपयोग मामला एक चर सेट करने के लिए एक मुहावरा है अगर यह पहले से ही सेट नहीं है।

: "${foo:=default value}"

गोटो के बारे में टिप्पणी एक ऐतिहासिक है। बृहदान्त्र की उपयोगिता बोर्न शेल से पहले से भी पीछे है , जो थॉम्पसन शेल के सभी रास्ते हैं , जिसमें एक गोटो निर्देश था। कोलन का मतलब तब एक लेबल था; एक कोलोन गोटो लेबल के लिए एक काफी सामान्य वाक्यविन्यास है (यह अभी भी sed में मौजूद है )।


ठीक है मैं समझा। क्या इस संदर्भ में टिप्पणी डालने का कोई एक बेहतर तरीका है जिससे आप अवगत हैं?
फहीम मीठा

3
@FaheemMitha आप जिस धागे का हवाला देते हैं, उसमें सिफारिश की गई है: अपने आदेश को प्रबंधनीय विखंडू में तोड़िए और प्रत्येक चुटकी पर टिप्पणी कीजिए। यदि आपकी आज्ञा इतनी जटिल है कि बीच में एक टिप्पणी की आवश्यकता है, तो इसे सरल बनाने का समय है!
गिलेस एसओ- बुराई को रोकना '

1
ठीक है, विचाराधीन कमांड में बहुत सारे तर्क हैं ... यह वीडियो फ़ाइलों के एक समूह को एक फ़ाइल में परिवर्तित कर रहा है। मुझे इसे सरल बनाने का कोई सीधा तरीका नहीं दिख रहा है। शायद किसी प्रकार की एक सूची बनाएं, और इसे एक तर्क के रूप में पारित करें? मुझे लगता है कि एक और सवाल हो सकता है।
फहीम मीठा

@FaheemMitha उदाहरण:, make_FINDएक त्वरित स्क्रिप्ट जो तर्कों की एक लंबी सूची बनाती है find। यहाँ, इसे चंक द्वारा बनाने की प्रेरणा यह है कि प्रत्येक हिस्सा एक लूप के शरीर से आता है, लेकिन एक ही शैली प्रत्येक कबाड़ पर टिप्पणी करने की अनुमति देती है।
गिल्स एसओ- बुराई को रोकना '

1
उदाहरण के लिए धन्यवाद। मेरा उदाहरण मूल रूप से एक कमांड के तर्क के रूप में दिए गए नामों की एक लंबी सूची है। मैं प्रत्येक नाम से जुड़ी टिप्पणियाँ चाहता हूं, क्योंकि यह मेरे लिए संदर्भ रखने का सबसे आसान तरीका है। मुझे कमांड को टुकड़ों में तोड़ने का कोई स्पष्ट तरीका नहीं दिख रहा है, और अगर मैंने किया, तो यह और भी लंबा हो सकता है, और यह पहले से ही काफी लंबा है।
फहीम मीठा

6

आप इसे बश सरण का उपयोग करके प्राप्त कर सकते हैं, जैसे

#!/bin/bash
CMD=(
  echo  # this is a comment
  foo
  )

"${CMD[@]}"

यह एक सरणी को परिभाषित करता है $CMD, और फिर इसे विस्तारित करता है। एक बार विस्तारित होने के परिणामस्वरूप परिणामी रेखा का मूल्यांकन किया जाता है, इसलिए इस मामले echo fooमें निष्पादित किया जाता है।

(और के बीच का पाठ) सरणी को परिभाषित करता है और इसलिए एक लाइन पर सब कुछ के बाद, हमेशा की तरह पार्टी वाक्य रचना के अधीन है #नजरअंदाज कर दिया है।

उद्धृत व्हाट्सएप के संरक्षण के बारे में ध्यान दें

${CMD[@]}एक एकल स्ट्रिंग का विस्तार होता है, जो एक अंतरिक्ष द्वारा अलग किए गए सभी तत्वों का संघटन है। एक बार विस्तारित होने के बाद, बैश तब स्ट्रिंग को सामान्य तरीके से टोकन में पार्स करेगा (cf $ IFS) ) , जो अक्सर वह नहीं होता है जो हम चाहते हैं।

इसके विपरीत यदि विस्तार को डबल कोट्स में लपेटा जाता है, अर्थात "${CMD[@]}", तब एरे में प्रत्येक तत्व संरक्षित होता है। के बीच अंतर पर विचार करेंhello world second itemऔर के"hello world" "second item"

उदाहरण उदाहरण:

# LIST=("hello world" "second item")

# for ITEM in ${LIST[@]}; do echo $ITEM; done
hello
world
second
item

# for ITEM in "${LIST[@]}"; do echo $ITEM; done
hello world
second item

उत्तर के लिए धन्यवाद, @RobM। तो, आपका सुझाव है कि सूची में आइटम के बारे में टिप्पणी / मेटा-जानकारी को बैश सरणी में ही शामिल करें? यह प्रश्न शायद अधिक उपयोगी होगा यदि मैंने उस तरह के आदेश का एक उदाहरण शामिल किया था जिसे मैं उपयोग करने की कोशिश कर रहा था। मुझे नहीं पता कि मैंने क्यों नहीं किया।
फहीम मीठा

बाह, यह पता चला है कि मैंने आपके सवाल को ध्यान से नहीं पढ़ा। सोचा था कि आप जिस प्रश्न से जुड़े थे, उससे पूछ रहे हैं। उफ़। :)
रॉबॉम

${CMD[@]}एक स्ट्रिंग में विस्तार नहीं करता है । - यह कई तारों तक फैलता है: न केवल सरणी के प्रत्येक तत्व के लिए, बल्कि प्रत्येक तत्व में व्हाट्सएप पर भी विभाजित होता है। (यानी: पूरी तरह से बेकार है)
रॉबर्ट सिएमर

4

मत करो $(: comment)। यह एक टिप्पणी नहीं है - यह एक उपधारा है - अधिकांश गोले के लिए एक और पूरी नई शेल प्रक्रिया। आपका लक्ष्य कम w / अपने इनपुट को करना है, अधिक नहीं, जो कि ऐसा करेगा - भले ही वह व्यर्थ हो।

आप इसके बजाय कर सकते हैं ...

printf '<%s>\n' some args here ${-##*"${--

                my long comment block

                }"}  and "more ${-##*"${--

                and another one in the
                middle of the quoted string
                there shouldn\'t b\e any special &
                (character) `echo issues here i hope >&2`
                basically anything that isn\'t a close \}
                $(echo the shell is looking for one >&2)
                }$(echo "}'"\" need backslash escaping >&2
                                )${-##*${--

                nesting is cool though

             }}"}here too"

}'" need backslash escaping
<some>
<args>
<here>
<and>
<more here too>

मूल रूप से वहाँ क्या हो रहा है शेल एक प्रतिस्थापन कर रहा है। यह $-प्रत्येक बार दो बार विशेष शेल पैरामीटर के मूल्य को प्रतिस्थापित करता है। यह वैसे भी एक छोटा तार है, लेकिन यह हमेशा सेट होता है - और इसलिए आंतरिक प्रतिस्थापन - जिसे बाहरी से पट्टी करने के लिए एक पैटर्न के रूप में व्याख्या की जाती है - यह नहीं है जब मैं -विस्तार प्रपत्र का उपयोग करता हूं, तो कोष्ठक के बीच की सामग्री तक विस्तृत ।

यहाँ:

bash -x <<""
printf %s\\n '${-##*"'${-- a set param doesn\'t expand to this optional text }'"}'

+ printf '%s\n' '${-##*"hxB"}'
${-##*"hxB"}

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

अभी भी बेहतर है:

COMMENT=
echo      ${COMMENT-"
           this will work the same way
           but the stripping isn\'t
           necessary because, while
           the variable is set, it is also
           empty, and so it will expand to
           its value - which is nothing
           "} this you\'ll see

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