लिनक्स बैश: मल्टीपल वेरिएबल असाइनमेंट


121

PHP में निम्न कोड के समान कुछ लाइन बैश में मौजूद है:

list($var1, $var2, $var3) = function_that_returns_a_three_element_array() ;

यानी आप एक वाक्य में 3 अलग-अलग वेरिएबल्स के लिए एक ही मूल्य प्रदान करते हैं।

मान लीजिए कि मेरे पास बैश फ़ंक्शन है myBashFuntionजो स्ट्रिंग को रोकने के लिए लिखता है "qwert asdfg zxcvb"। क्या ऐसा करना संभव है:

(var1 var2 var3) = ( `myBashFuntion param1 param2` )

बराबर चिह्न के बाईं ओर का हिस्सा निश्चित रूप से मान्य सिंटैक्स नहीं है। मैं बस समझाने की कोशिश कर रहा हूं कि मैं क्या मांग रहा हूं।

क्या काम करता है, हालांकि, निम्नलिखित है:

array = ( `myBashFuntion param1 param2` )
echo ${array[0]} ${array[1]} ${array[2]}

लेकिन एक अनुक्रमित सरणी सादा चर नामों के रूप में वर्णनात्मक नहीं है।
हालाँकि, मैं कर सकता था:

var1 = ${array[0]} ; var2 = ${array[1]} ; var3 = ${array[2]}

लेकिन वे 3 और कथन हैं जिनसे मैं बचना चाहूंगा।

मैं सिर्फ एक शॉर्टकट सिंटैक्स की तलाश में हूं। क्या यह संभव है?

जवाबों:


222

पहली बात जो मेरे दिमाग में आती है:

read -r a b c <<<$(echo 1 2 3) ; echo "$a|$b|$c"

आउटपुट, आश्चर्यजनक रूप से है

1|2|3

4
क्या वैसे भी यह काम करने के लिए है यदि पहले चर में कोई स्थान है?
Rucent88

7
@ मिचेल read -d "\n" v1 v2 <<<$(cmd)पूरी तरह से काम करता है। धन्यवाद!
Rucent88

1
@LeeNetherton, अच्छा बिंदु, हालांकि मुझे यकीन नहीं है कि अगर किसी को इको कमांड की वापसी की स्थिति की आवश्यकता है :-) मुझे लगता है कि इस वाक्यविन्यास का समर्थन करने वाले उत्तर बैश लिखने के समय कम आम था (जैसा कि डिफ़ॉल्ट रूप से स्थापित किया गया था), हालांकि मैं 100% यकीन नहीं है।
माइकल क्रेलिन -

4
@ माइकलकेरलिन-हैकर निश्चित रूप से, वापसी की स्थिति echoनिरर्थक है, लेकिन मैं इस तकनीक का उपयोग एक स्क्रिप्ट से कई मूल्यों को वापस करने के लिए कर रहा था जिसे मैंने वापसी की स्थिति के बारे में ध्यान रखा था। मुझे लगा कि मैं अपने निष्कर्षों को साझा करूंगा।
ली नेथर्टन

1
सुरक्षा के लिए आपको उपयोग करना चाहिए read -r:do not allow backslashes to escape any characters
टॉम हेल

18

मैं मानों को एक सरणी में निर्दिष्ट करना चाहता था। इसलिए, माइकल क्रेलिन के दृष्टिकोण का विस्तार , मैंने किया:

read a[{1..3}] <<< $(echo 2 4 6); echo "${a[1]}|${a[2]}|${a[3]}"

कौन सी पैदावार:

2|4|6 

जैसा सोचा था।


2
मूल्यों को एक सरणी में रखने के लिए पहले से ही एक सरल समाधान है जिसका मैंने प्रश्न में उल्लेख किया है:a=( $(echo 2 4 6) ) ; echo ${a[0]} ${a[1]} ${a[2]}
GetFree

हां, मैंने इसे नजरअंदाज कर दिया था। हालांकि, मैं तर्क दूंगा कि मेरा सुझाव बेहतर है कि मैं बड़े सरणियों को निर्दिष्ट करूं।
साउंड्रे

@soundray आपके समाधान में विस्तार और एक हेस्टिंगस्ट्रिंग का उपयोग किया गया है, जो कि मुझे संदेह है कि मुझे संदेह है कि यह उस परिदृश्य में अच्छा प्रदर्शन करेगा (लेकिन मैंने जांच नहीं की)।
कैमिलो मार्टिन

सुरक्षा के लिए आपको उपयोग करना चाहिए read -r:do not allow backslashes to escape any characters
टॉम हेल

5

मुझे लगता है कि यह मदद कर सकता है ...

मेरी स्क्रिप्ट्स में उपयोगकर्ता इनपुट की गई तिथियों (मिमी / dd / yyyy) को तोड़ने के लिए, मैं दिन, महीने, और वर्ष को एक सरणी में संग्रहीत करता हूं, और फिर मूल्यों को अलग-अलग चर में डाल देता हूं:

DATE_ARRAY=(`echo $2 | sed -e 's/\// /g'`)
MONTH=(`echo ${DATE_ARRAY[0]}`)
DAY=(`echo ${DATE_ARRAY[1]}`)
YEAR=(`echo ${DATE_ARRAY[2]}`)

4 उपधाराओं से अधिक अतिरिक्त सीड प्रक्रिया से क्यों न बचें, और बस एक लाइन में वह सब करें:IFS=/ read -r m d y < <(echo 12/29/2009)
अमित नायडू

5

कभी-कभी आपको कुछ फंकी करना पड़ता है। मान लीजिए कि आप एक कमांड (उदाहरण के लिए SDGuero द्वारा तिथि उदाहरण) से पढ़ना चाहते हैं, लेकिन आप कई कांटे से बचना चाहते हैं।

read month day year << DATE_COMMAND
 $(date "+%m %d %Y")
DATE_COMMAND
echo $month $day $year

आप पढ़े गए कमांड में भी पाइप कर सकते हैं, लेकिन फिर आपको सब-वे के भीतर चर का उपयोग करना होगा:

day=n/a; month=n/a; year=n/a
date "+%d %m %Y" | { read day month year ; echo $day $month $year; }
echo $day $month $year

का परिणाम...

13 08 2013
n/a n/a n/a

readआदेश एक subshell में ऐसा नहीं होता है क्योंकि ब्रेसिज़ के लिए, यह है क्योंकि आप पाइप के दाईं ओर पढ़ें आदेश मिल गया है है। आपको readवर्तमान शेल में कमांड को चलाने की आवश्यकता है , जिसे आप पसंद कर सकते हैंread day month year <<< `date "+%d %m %Y"`
वायवीय

नहीं - read होता है, लेकिन यह जिस चर को पढ़ता है उसका दायरा उस दायरे से बाहर हो जाता है जब पाइपलाइन का सबस्क्रिप्शन समाप्त हो जाता है।
ओथियस

1
मेरी टिप्पणी इस कारण के बारे में थी कि पढ़े जाने वाले सब-सब्जेक्ट में क्यों होता है, और मुझे एहसास है कि आपने जो कुछ लिखा है, मैं उसे गलत समझ रहा हूं। मैंने सोचा था कि आप का मतलब है कि सबमिशन बनाया गया था क्योंकि आपने कंपाउंड स्टेटमेंट के चारों ओर घुंघराले ब्रेसिज़ का इस्तेमाल किया था। परंतु! आपने जो उदाहरण दिया था, वह यह था कि कांटे से बचने के लिए, और उपखंड कांटा भी नहीं होगा?
न्यूमैटिक्स

पहले उदाहरण के लिए ठीक एक कांटा की आवश्यकता होती है: ताकि bash दिनांक कमांड को लॉन्च कर सके। दूसरे उदाहरण में, आपने तिथि और आपके उप-शेल के बीच एक पाइपलाइन स्थापित की है। मुझे लगता है कि इन दिनों मारपीट काफी चालाक है वास्तव में उपखंड में कांटा नहीं है, लेकिन मुझे इस बारे में निश्चित नहीं है। किसी भी दर पर, यह ऐसा दिखता है। :)
ओथियस

0

ओ'रिली द्वारा बैश कुकबुक के अध्याय 5 में , (कुछ लंबाई पर) एक चर असाइनमेंट में आवश्यकता के कारणों पर चर्चा की गई है कि '=' चिन्ह के आसपास कोई स्थान नहीं है।

MYVAR="something"

स्पष्टीकरण का कमांड और चर के नाम के बीच अंतर करने के लिए कुछ करना है (जहां '=' ​​एक वैध तर्क हो सकता है)।

यह सब घटना के बाद थोड़ा सा उचित लगता है, लेकिन किसी भी मामले में चर की सूची को निर्दिष्ट करने की विधि का कोई उल्लेख नहीं है।


हाँ मैं जानता हूँ। मैंने सिर्फ पठनीयता के लिए यहां और अतिरिक्त स्थान जोड़े
GetFree

वास्तव में यह एक खराब प्रेरणा है: क्या होगा अगर ' ;' एक वैध तर्क है? जब मैं लिखता हूं ls ; cdतब भी कॉल करता है lsऔर cdरिक्त स्थान के बावजूद। यदि मैं निर्देशिकाओं को सूचीबद्ध करना चाहता हूं ;और cdमैं बस टाइप कर सकता हूं ls ';' cd
पीटरसन्यूयट्स
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.