2012-03-30 14 views
22

में अप्रत्यक्ष चर काम लगता है कि पार्टी में अप्रत्यक्ष चर सेटिंग करने की सिफारिश की जिस तरह से उपयोग करने के लिए eval है:बैश

var=x; val=foo 
eval $var=$val 
echo $x # --> foo 
समस्या

eval साथ हमेशा की तरह एक है:

var=x; val=1$'\n'pwd 
eval $var=$val # bad output here 

(और चूंकि इसे कई स्थानों पर अनुशंसा की जाती है, मुझे आश्चर्य है कि इस वजह से कितनी स्क्रिप्ट कमजोर हैं ...)

किसी भी मामले में, Usin का स्पष्ट समाधान ग्राम (भाग निकले) उद्धरण वास्तव में काम नहीं करता है:

var=x; val=1\"$'\n'pwd\" 
eval $var=\"$val\" # fail with the above 

बात यह है कि पार्टी अप्रत्यक्ष चर संदर्भ (${!foo} के साथ) में पकाया गया है, लेकिन मैं अप्रत्यक्ष काम करने के लिए किसी भी तरह के रास्ते नहीं दिख रहा है - है ऐसा करने के लिए कोई सौहार्दपूर्ण तरीका है?

रिकॉर्ड के लिए, मैं एक समाधान खोजने के किया था, लेकिन यह कुछ है कि मैं विचार करूँगा "समझदार" नहीं है ...:

eval "$var='"${val//\'/\'\"\'\"\'}"'" 

उत्तर

2

मुख्य बिंदु है कि यह करने के लिए सिफारिश की तरीका है:

eval "$var=\$val" 

आरएचएस अप्रत्यक्ष रूप से भी किया। चूंकि eval उसी पर्यावरण में उपयोग किया जाता है, तो इसमें $val बाध्य होगा, इसलिए यह कार्य करता है, और से अब यह एक चर है। चूंकि $val चर एक ज्ञात नाम है, वहाँ के हवाले से साथ कोई समस्या नहीं है, और यह भी रूप में लिखा जा सकता था:

eval $var=\$val 

लेकिन चूंकि यह बेहतर है हमेशा उद्धरण को जोड़ने के लिए, पूर्व में बेहतर है, या भी इस:

eval "$var=\"\$val\"" 

बैश में एक बेहतर विकल्प है कि पूरी बात के लिए उल्लेख किया गया था कि eval पूरी तरह से (से बचा जाता है औरके रूप में के रूप में सूक्ष्म नहीं हैआदि):

printf -v "$var" "%s" "$val" 

हालांकि इस एक सीधा जवाब नहीं है कि मैं क्या मूल रूप से कहा कि ...

13
eval "$var=\$val" 

तर्क eval को हमेशा एक ही होना चाहिए स्ट्रिंग या तो सिंगल या डबल कोट्स में संलग्न है। इस पैटर्न से विचलित होने वाले सभी कोड में किनारे के मामलों में कुछ अनजान व्यवहार हैं, जैसे विशेष वर्ण वाले फ़ाइल नाम।

जब eval पर तर्क को खोलकर विस्तारित किया गया है, $var को परिवर्तनीय नाम के साथ प्रतिस्थापित किया गया है, और \$ को एक साधारण डॉलर के साथ प्रतिस्थापित किया गया है। इसलिए जिस स्ट्रिंग का मूल्यांकन किया जाता है वह बन जाता है:

varname=$value 

यह वही है जो आप चाहते हैं।

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

eval "$var=\"the value is $val\"" 
+0

आरएचएस पर अविवेक मैं के लिए क्या देख रहा हूँ नहीं है। –

+1

(* माथे-स्लैप *) बह, मैं पूरी तरह से चूक गया कि क्यों मैं * आरएचएस पर संकेत चाहता हूं। चूंकि आपका उत्तर इसके बारे में बात नहीं करता है, इसलिए मैं अब इसे संपादित कर दूंगा, जवाब देने के बजाय-खुद-और-पेट-मेरी-बैक ... –

+0

शानदार! अतीत में मैंने कुछ जटिल 'eval eval export' बकवास किया था। तुम्हारा बहुत शुक्रिया हमेशा। Googlers के लिए, उपरोक्त उत्तर के साथ जाओ, eval eval निर्यात प्रारूप नहीं। – bgStack15

24

एक थोड़ा बेहतर तरीका यह है कि declare है

declare $var="$val" 

नोट bash में समानार्थी है। typeset आदेश अधिक व्यापक रूप से समर्थित है (ksh और zsh भी इसका इस्तेमाल करते हैं):

printf -v "${VARNAME}" '%s' "${VALUE}" 

यह सब संभव से बचने के मुद्दों से बचाता है:

typeset $var="$val" 
+0

यह वास्तव में bash – MarcH

+0

की तुलना में कम गोले के लिए पोर्टेबल नहीं दिखता है; जबकि 'घोषणा 'POSIX मानक का विस्तार है, यह' टाइपसेट 'के लिए भी एक पर्याय है, जो * अन्य प्रमुख गोले (' ksh' और' zsh', अर्थात्) द्वारा समर्थित है। शैल जो कुछ समान समर्थन नहीं करते हैं, उन्हें देखभाल के साथ 'eval' का उपयोग करना चाहिए। – chepner

+3

'eval" $ var = '$ val' "' लगभग सावधान नहीं है: यदि सामग्रियों में शाब्दिक एकल-उद्धरण होते हैं, तो वे आसानी से बच सकते हैं। –

14

बैश printf के लिए एक विस्तार है कि एक चर में अपने परिणाम बचाता है ।

आप $VARNAME के लिए एक अमान्य पहचानकर्ता का उपयोग करते हैं, आदेश असफल और वापस आ जाएगी स्थिति कोड 2:

$ printf -v ';;;' foobar; echo $? 
bash: printf: `;;;': not a valid identifier 
2