जब बैश में {a, b, c} का विस्तार होता है, तो यह कब नहीं होता है?


13

एक बैश स्क्रिप्ट जिसमें शामिल है

for i in {a,b}-{1,2}; do
  echo $i;
done

प्रिंट

a-1
a-2
b-1
b-2

जब निष्पादित किया गया। यह वही है जिसकी मुझे उम्मीद थी - जैसा कि {a,b}निर्माण का विस्तार है।

हालाँकि, जब (एक और) स्क्रिप्ट होती है

v={a,b}-{1,2}
echo $v

यह प्रिंट करता है

{a,b}-{1,2}

जो मुझे उम्मीद नहीं थी। मुझे उम्मीद थी कि यह प्रिंट होगा a-1 a-2 b-1 b-2। जाहिर है, {a,b}निर्माण का विस्तार नहीं है।

मैं इसका विस्तार कर सकता हूं

v=$(echo {a,b}-{1,2})

इन टिप्पणियों के आधार पर मेरे दो प्रश्न हैं: 1) {a,b}निर्माण का विस्तार कब हुआ है? 2) $(echo {a,b}-{1,2})आवश्यकता होने पर विस्तार को ट्रिगर करने का पसंदीदा तरीका है?


1
यह कम से कम, इस तथ्य के अनुरूप है कि आप एक साधारण के साथ एक सरणी चर नहीं बना सकते हैं =। उदाहरण के लिए, v=a-1 a-2काम नहीं करेगा।
grochmal

@grochmal - ऐसा इसलिए है क्योंकि आप एक स्केलर मान प्रदान कर रहे हैं। v=a-1 a-2का मतलब assign 'a-1' to variable v and run 'a-2' v=(a-1 a-2)है चर के लिए सरणी असाइन करता है vv+=(b-1 b-2)इसे जोड़ता है।
कैस

जवाबों:


15

बैश मैनुअल का कहना है कि:

SIMPLE COMMAND EXPANSION
When a simple command is executed, the shell performs the following
expansions, assignments, and redirections, from left to right.
[...]
4. The  text  after the = in each variable assignment undergoes tilde
   expansion, parameter expansion, command substitution, arithmetic
   expansion, and quote removal before being assigned to the variable.

ब्रेस विस्तार सूची में नहीं है, इसलिए इसे असाइनमेंट के लिए निष्पादित नहीं किया गया है v={a,b}-{1,2}। जैसा कि @Wildcard ने उल्लेख किया है, सरल विस्तार v=a-1 v=b-1 ...वैसे भी संवेदनहीन होगा।

इसके अलावा, जब निष्पादन echo $v, निम्नलिखित लागू होता है:

EXPANSION
Expansion is performed on the command line after it has been split
into words. [...]

The order of expansions is: brace expansion; tilde expansion, 
parameter and variable expansion, arithmetic expansion, and command
substitution (done in a left-to-right fashion); word splitting; and
pathname expansion.

ब्रेस विस्तार चर विस्तार से पहले होता है, इसलिए ब्रेसिज़ का $vविस्तार नहीं किया जाता है।

लेकिन आप इस तरह से सामान कर सकते हैं:

$ var_this=foo var_that=bar
$ echo $var_{this,that}
foo bar

$(echo ...)यदि आप स्ट्रिंग में कोई व्हाट्सएप का विस्तार नहीं करना चाहते हैं, तो इसके साथ विस्तार करना चाहिए, और इसलिए शब्द विभाजन के साथ समस्याओं में नहीं चलेगा। यदि आप कर सकते हैं तो एक बेहतर तरीका एक सरणी चर का उपयोग करना हो सकता है।

उदाहरण के विस्तार को एक सरणी में सहेजें और विस्तारित मानों के साथ कुछ कमांड चलाएं:

$ v=( {a,b}-{1,2} )
$ some_command "${v[@]}"

5

एक दिलचस्प बिंदु। संभवतः उपयोगी निम्नलिखित अंश है man bash:

एक वेरिएबल को फॉर्म के स्टेटमेंट द्वारा सौंपा जा सकता है

      नाम = [ मूल्य ]

यदि मान नहीं दिया जाता है, तो चर को नल स्ट्रिंग निर्दिष्ट किया जाता है। सभी मान टिल्ड विस्तार, पैरामीटर और चर विस्तार, कमांड प्रतिस्थापन, अंकगणितीय विस्तार और उद्धरण हटाने से गुजरते हैं (नीचे विस्तार देखें)।

ध्यान दें कि सूची में ब्रेस विस्तार का उल्लेख नहीं किया गया है।

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


1
शायद यह ? 2. "वे शब्द जो परिवर्तनशील कार्य या पुनर्निर्देशन नहीं हैं, विस्तारित हैं (शेल विस्तार देखें)।"
जेफ स्कालर

@JeffSchaller, आप सही हैं। वास्तव में इस सवाल का जवाब सबसे अच्छा है "अनुभाग का विस्तार" अनुभाग पढ़कर LESS=+/SIMPLE man bash
वाइल्डकार्ड

0

मेरे lil के ज्ञान के अनुसार {a, b, c} का विस्तार तब किया जाता है जब इसे सीधे echo किया जाता है या कमांड के साथ उपयोग किया जाता है जैसे: mkdir ~ / {a, b, c}, लेकिन जब इसे किसी चर पर सेट किया जाता है, तो इसका मूल्यांकन किया जाना चाहिए इसे गूँज रहा है या इसे आर्गेज्म के रूप में इस्तेमाल कर रहा है!

u@h:~$ echo {a,b}-{1,2}
a-1 a-2 b-1 b-2
u@h:~$ v={a,b}-{1,2}
u@h:~$ echo $v
{a,b}-{1,2}
u@h:~$ eval echo $v
a-1 a-2 b-1 b-2

चूँकि आपके पास "a" के बाद "b" अल्फा क्रम में [az] है, और "1" के बाद "2" है, जो कि dec order [0-9] में है: आप दोहरे काल का उपयोग कर सकते हैं ".." comma of comma "," "

u@h:~$ echo {a..b}-{1..2}
a-1 a-2 b-1 b-2
u@h:~$ v={a..b}-{1..2}
u@h:~$ echo $v
{a..b}-{1..2}
u@h:~$ eval echo $v
a-1 a-2 b-1 b-2

1
सवाल यह है कि शाब्दिक स्ट्रिंग "a-1 a-2 b-1 b-2" पर सेट क्यों vनहीं किया गया था । या कम से कम कोई त्रुटि क्यों नहीं डाली गई जैसा कि आप कमांड टाइप करने पर प्राप्त करते हैं: v=a-1 v=a-2 v=b-1 v=b-2(जो आप उम्मीद करेंगे कि वेरिएबल असाइनमेंट का विस्तार किया जाए)। यह एक अच्छा सवाल है; यह वास्तव में इसका जवाब नहीं है।
वाइल्डकार्ड

@SatoKatsura, "वाइल्डकार्ड विस्तार" का क्या अर्थ है? वहाँ पैरामीटर विस्तार, pathname विस्तार, और ब्रेस विस्तार है - जिनमें से कोई भी आप का उल्लेख किया जा सकता है, और जिनमें से सभी अलग हैं। या आप शब्द बंटवारे का मतलब था?
वाइल्डकार्ड

0

बैश में एक चर को असाइन करने से अभिव्यक्ति का विस्तार नहीं होता है।

इस छोटी लिपि के लिए, x "*"में विस्तार होगा और नहीं "*":

#!/bin/bash
x=*
echo "$x"

हालांकि, कुछ मूल्यों का विस्तार किया गया है, रेफ। ilkkachu से अच्छा जवाब।

जब उनका मूल्यांकन किया जाता है तो अभिव्यक्तियों का विस्तार किया जाता है।

ऐशे ही:

x=$(echo *)        # <-- evaluation of "*"
echo "$x"

या इस तरह:

x=*
echo $x            # <-- evaluation of $x

या इस तरह:

x=*
eval echo "$x"     # <-- evaluation of `echo *`

ट्रिगर $()काफी आम है और मुझे लगता है कि इसे पसंद किया जाता है eval, लेकिन सबसे अच्छा शायद मूल्यांकन को ट्रिगर करना नहीं है, जब तक कि चर वास्तव में एक कमांड में उपयोग नहीं किया जाता है।

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