शेल चरों के आसपास हमें घुंघराले ब्रेसिज़ की आवश्यकता कब होती है?


657

शेल स्क्रिप्ट में, {}चर का विस्तार करते समय हम कब उपयोग करते हैं?

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

var=10        # Declare variable

echo "${var}" # One use of the variable
echo "$var"   # Another use of the variable

क्या कोई महत्वपूर्ण अंतर है, या यह सिर्फ शैली है? क्या एक को दूसरे पर पसंद किया जाता है?

जवाबों:


750

इस विशेष उदाहरण में, इससे कोई फर्क नहीं पड़ता। हालांकि, {}में ${}यदि आप चर का विस्तार करना चाहते उपयोगी होते हैं fooस्ट्रिंग में

"${foo}bar"

के बाद से "$foobar"बजाय चर से पहचान का विस्तार होगा foobar

घुंघराले ब्रेसिज़ भी बिना शर्त के आवश्यक हैं जब:

  • सरणी तत्वों का विस्तार, जैसे कि ${array[42]}
  • के रूप में ${filename%.*}(विस्तार निकालें)
  • 9 से परे की स्थिति का विस्तार: "$8 $9 ${10} ${11}"

संभावित रूप से अस्पष्ट मामलों में, बजाय हर जगह ऐसा करना, अच्छा प्रोग्रामिंग अभ्यास माना जा सकता है। यह स्थिरता के लिए और आश्चर्य से बचने के लिए दोनों है $foo_$bar.jpg, जहां यह स्पष्ट रूप से स्पष्ट नहीं है कि अंडरस्कोर चर नाम का हिस्सा बन जाता है।


106
{}ब्रेस विस्तार के रूप में जाना जाता है । ${}चर विस्तार के रूप में जाना जाता है। वे अलग-अलग काम करते हैं। मैं तुम्हें कोई विस्तार बिट के अलावा upvote होगा।
स्पेंसर रथबुन

5
@NewUser " सरणियों के अलावा वास्तव में इसकी आवश्यकता नहीं है" ऐसा नहीं है, ब्रेसिज़ PARAMETER विस्तार के लिए आवश्यक हैं , स्क्रिप्टिंग में एक बहुत ही उपयोगी निर्माण। मैंने कई sed और awk स्क्रिप्ट देखी हैं जिन्हें थोड़ा सा पैरामीटर विस्तार के साथ बदला जा सकता है।
घेराबंदी

10
@caffinatedmonkey $()का उपयोग कमांड को निष्पादित करने के लिए किया जाता है, जैसे कि वेरिएबल md5sum=$(md5sum foo.bin)के आउटपुट को स्टोर करेगा , जिसका उपयोग करके अब एक्सेस किया जा सकता है । इसके अलावा, यह स्पष्ट करने के लिए अच्छा अभ्यास है कि उल्लेख करने के लिए ओपी और ओपी की आत्मा में कई और अधिक! md5sum foo.binmd5sum${md5sum}
L0j1k

11
@ L0j1k खोजकर्ता की बात करें, तो मुझे यह उल्लेख करना महत्वपूर्ण है कि $()एक उपधारा से इसकी कमांड निष्पादित होती है ।
एड्रियन गुंटर

2
@karatedog ${1:-20}पैरामीटर विस्तार का एक रूप है। यहाँ यह स्पष्ट नहीं है क्योंकि यह मुख्य रूप से अंकों और अंकगणित ऑपरेटरों का उपयोग करता है जो हमें यह सोचने में चकित करता है कि इसमें अंकगणित शामिल है, लेकिन यह वास्तव में स्थितीय पैरामीटर को संदर्भित करता है $1, जिसे अगर परिभाषित नहीं किया गया है तो इसे डिफ़ॉल्ट मान 20(सिंटैक्स ${variable:-default_value}) से बदल दिया जाएगा ।
हारून

126

चर को बिना $और बिना घोषित और असाइन किया गया है {}। आपको उपयोग करना होगा

var=10

आवंटित करना। चर से पढ़ने के लिए (दूसरे शब्दों में, चर का 'विस्तार'), आपको अवश्य उपयोग करना चाहिए $

$var      # use the variable
${var}    # same as above
${var}bar # expand var, and append "bar" too
$varbar   # same as ${varbar}, i.e expand a variable called varbar, if it exists.

इसने मुझे कभी-कभी भ्रमित किया है - अन्य भाषाओं में हम उसी तरह से चर का उल्लेख करते हैं, भले ही यह असाइनमेंट के बाएं या दाएं पर हो। लेकिन शेल-स्क्रिप्टिंग अलग है, $var=10वह नहीं करता है जो आप सोचते हैं कि यह करता है!


34

आप {}ग्रुपिंग के लिए उपयोग करते हैं। ऐरे तत्वों को ब्रेसिज़ की आवश्यकता होती है। उदाहरण:

dir=(*)           # store the contents of the directory into an array
echo "${dir[0]}"  # get the first entry.
echo "$dir[0]"    # incorrect

मैं पहली पंक्ति नहीं समझ सका dir=(*)। जहाँ तक मुझे पता है, dirनिर्देशिका सामग्री (समतुल्य ls -C -b) को सूचीबद्ध करने के लिए एक अंतर्निर्मित कमांड है । क्या आप समझा सकते हैं?
जार्विस

1
शेल प्रोग्रामिंग में, व्हाट्सएप द्वारा कमांड और तर्कों को एक दूसरे से अलग किया जाना चाहिए। यहां, आप बिना व्हाट्सएप के बराबर चिह्न देखते हैं, जिसका अर्थ है कि यह एक चर असाइनमेंट है। dirचर का नाम है, और कोष्ठक का उपयोग फ़ाइल नाम विस्तार *को एक सरणी में एकत्र करने के लिए किया जाता है ।
ग्लेन जैकमैन

27

आप ब्रेसिज़ के अंदर कुछ पाठ हेरफेर करने में भी सक्षम हैं:

STRING="./folder/subfolder/file.txt"
echo ${STRING} ${STRING%/*/*}

परिणाम:

./folder/subfolder/file.txt ./folder

या

STRING="This is a string"
echo ${STRING// /_}

परिणाम:

This_is_a_string

आप सही हैं "नियमित चर" की जरूरत नहीं है ... लेकिन यह डिबगिंग के लिए और एक स्क्रिप्ट को पढ़ने के लिए अधिक सहायक है।


11

चर नाम का अंत आमतौर पर एक स्थान या न्यूलाइन द्वारा दर्शाया जाता है। लेकिन क्या होगा अगर हम वैरिएबल मान को प्रिंट करने के बाद स्पेस या न्यूलाइन नहीं चाहते हैं? घुंघराले ब्रेसिज़ शेल दुभाषिया को बताते हैं जहां चर नाम का अंत होता है।

क्लासिक उदाहरण 1) - व्हेलस्पेस को पीछे किए बिना शेल चर

TIME=10

# WRONG: no such variable called 'TIMEsecs'
echo "Time taken = $TIMEsecs"

# What we want is $TIME followed by "secs" with no whitespace between the two.
echo "Time taken = ${TIME}secs"

उदाहरण 2) जावा क्लासपाथ को संस्करण वाले जार के साथ

# WRONG - no such variable LATESTVERSION_src
CLASSPATH=hibernate-$LATESTVERSION_src.zip:hibernate_$LATEST_VERSION.jar

# RIGHT
CLASSPATH=hibernate-${LATESTVERSION}_src.zip:hibernate_$LATEST_VERSION.jar

(फ्रेड का जवाब पहले से ही यह बताता है लेकिन उसका उदाहरण थोड़ा बहुत सार है)


5

घुंघराले ब्रेस हमेशा सरणी तत्वों तक पहुंचने और ब्रेस विस्तार को पूरा करने के लिए आवश्यक होते हैं।

{}अस्पष्टता के लिए कोई गुंजाइश नहीं होने पर भी शेल वेरिएबल विस्तार के लिए सतर्क और उपयोग नहीं करना अच्छा है।

उदाहरण के लिए:

dir=log
prog=foo
path=/var/${dir}/${prog}      # excessive use of {}, not needed since / can't be a part of a shell variable name
logfile=${path}/${prog}.log   # same as above, . can't be a part of a shell variable name
path_copy=${path}             # {} is totally unnecessary
archive=${logfile}_arch       # {} is needed since _ can be a part of shell variable name

इसलिए, तीन पंक्तियों को लिखना बेहतर है:

path=/var/$dir/$prog
logfile=$path/$prog.log
path_copy=$path

जो निश्चित रूप से अधिक पठनीय है।

चूँकि एक चर नाम एक अंक से शुरू नहीं हो सकता है, शेल को {}गिने हुए चर (जैसे $1, $2इत्यादि) की आवश्यकता नहीं है जब तक कि इस तरह के विस्तार को एक अंक के बाद नहीं किया जाता है। यह बहुत सूक्ष्म है और यह {}ऐसे संदर्भों में स्पष्ट रूप से उपयोग करने के लिए बनाता है:

set app      # set $1 to app
fruit=$1le   # sets fruit to apple, but confusing
fruit=${1}le # sets fruit to apple, makes the intention clear

देख:


1
It's good to be not over-cautious: मुझे आश्चर्य है कि ज्यादातर लोग क्या सोचते हैं। हर समय घुंघराले ब्रेसिज़ का उपयोग करें ताकि आप उन्हें भूल न जाएं जब उन्हें ज़रूरत हो, या केवल उन्हीं का उपयोग करें जहां पठनीयता में सुधार हो।
रोजर डेल

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

1
सच है। मेरा पालतू पेशाब है कि हर कोई लगता है कि सभी चर शेल लिपियों में सभी टोपियां होनी चाहिए :)
रोजर डेल

2

पाठ हेरफेर के बारे में सिएराक्स और पीटर के सुझाव के बाद {}, उदाहरण के लिए, एक चर को एक आदेश में पारित करने के लिए उपयोग किया जाता है:

मान लें कि आपके पास एक sposi.txt फ़ाइल है जिसमें एक प्रसिद्ध इतालवी उपन्यास की पहली पंक्ति है:

> sposi="somewhere/myfolder/sposi.txt"
> cat $sposi

ouput: quel ramo del lago di como che volge a mezzogiorno

अब दो चर बनाएं:

# Search the 2nd word found in the file that "sposi" variable points to
> word=$(cat $sposi | cut -d " " -f 2)

# This variable will replace the word
> new_word="filone"

अब new_word में से किसी एक के साथ , sposi.txt फ़ाइल के अंदर शब्द चर सामग्री को प्रतिस्थापित करें

> sed -i "s/${word}/${new_word}/g" $sposi
> cat $sposi

ouput: quel filone del lago di como che volge a mezzogiorno

शब्द "रेमो" को बदल दिया गया है।


1
यह चर के चारों ओर घुंघराले ब्रेसिज़ के बिना ही काम करता है।
आर्मली

आप weel-known novelबिट को ठीक करना चाह सकते हैं । फिर भी अपडाउन किया।
gsl
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.