$ {! FOO} और zsh


13

${!FOO}में एक डबल प्रतिस्थापन करता है bash, जिसका अर्थ है कि यह FOO का (स्ट्रिंग) मान लेता है और इसे एक चर नाम के रूप में उपयोग करता है।
zshइस सुविधा का समर्थन नहीं करता है।

वहाँ इस काम ही में बनाने के लिए एक रास्ता है bashऔर zsh?

पृष्ठभूमि:

मुझे पर्यावरण चर की एक सूची मिली है, जैसे

PATH MAIL EDITOR

और पहले चर नाम और बाद में उनके मान मुद्रित करना चाहते हैं।

यह काम करता है bashलेकिन इसमें नहीं zsh:

for VAR in LIST
do
        echo $VAR
        echo ${!VAR}
done

यह किसी भी तरह से "पुराना तरीका" संभव होना चाहिए eval, लेकिन मैं इसे काम करने के लिए नहीं कर सकता:

for VAR in LIST
do
        echo $VAR
        echo `eval \$$VAR`
done

मैं कभी नहीं समझ पा रहा हूं कि मैं जरूरत पड़ने पर ${${VAR}}भी मनमाने ढंग से गहरे सब्जेक्टिटेशन जैसे कि या नहीं कर सकता हूं ${${${VAR}}}, इसलिए उसके लिए स्पष्टीकरण भी अच्छा होगा।


1
हा! मुझे लगा कि zsh में अधिक विशेषताएं होनी चाहिए थीं।
урослав Рахматуллин

4
bashइसके साथ डींग मारने की आवश्यकता नहीं है , इसका वास्तव में एक ही कार्य है (और बहुत कुछ), केवल एक अलग पैटर्न का उपयोग करता है, अर्थात् ${(p)FOO}
प्रोफैट्स

2
@ УрославРахматуллин, zsh (e)-2.6-Beta17 (मई 1996) में zsh का पैरामीटर विस्तार ध्वज, (P)ध्वज को 3.1.5-pws-7 (1999) में जोड़ा गया । ${!var}2.0 में बैश है (दिसंबर 1996)।
स्टीफन चेज़ेलस

जवाबों:


18

बाश और zsh दोनों का अप्रत्यक्ष विस्तार करने का एक तरीका है, लेकिन वे अलग-अलग वाक्यविन्यास का उपयोग करते हैं।

इसका उपयोग करके अप्रत्यक्ष विस्तार करना काफी आसान है eval; यह सभी POSIX और अधिकांश बॉर्न गोले में काम करता है। मान को ठीक से उद्धृत करने के लिए ध्यान रखें कि मूल्य में ऐसे अक्षर हैं जो शेल में एक विशेष अर्थ रखते हैं।

eval "value=\"\${$VAR}\""
echo "$VAR"
echo "$value"

${${VAR}}काम नहीं करता है क्योंकि यह एक ऐसी विशेषता नहीं है जो किसी भी शेल को लागू करता है। ब्रेसिज़ के अंदर की चीज़ को सिंटैक्स नियमों के अनुरूप होना चाहिए जिसमें शामिल नहीं है ${VAR}। (Zsh में, यह समर्थित सिंटैक्स है, लेकिन कुछ अलग करता है: नेस्टेड प्रतिस्थापन एक ही मूल्य पर क्रमिक रूपांतर करते हैं; ${${VAR}}यह बराबर है $VARक्योंकि यह मूल्य पर दो बार पहचान परिवर्तन करता है।)


19

प्रॉस्पेक्ट द्वारा मूल प्रश्न के तहत टिप्पणी, ${(p)FOO}अप्रत्यक्ष चर संदर्भ की सामग्री को आउटपुट करने के लिए उदाहरण देती है । झंडा गलत है या टाइपो है, यह एक कैपिटल पी होना चाहिए न कि लोअर केस पी। का उपयोग करें: ${(P)FOO}

निम्नलिखित वांछित उत्पादन का उत्पादन करना चाहिए:

#! /bin/zsh
LIST=(PATH MAIL EDITOR)
for VAR in ${LIST}
do
    print "${VAR}:  ${(P)VAR}"
done

से zshexpn आदमी पेज; अनुभाग - पैरामीटर विस्तार झंडे :

पी

  This forces the value of the parameter name to be interpreted as a further
  parameter name,  whose  value  will  be used where appropriate.  Note that
  flags set with one of the typeset family of commands (in particular case
  transformations) are not applied to the value of name used in this fashion.

  If used with a nested parameter or command substitution, the result of that
  will be taken as a parameter  name  in the  same  way.   For  example,  if
  you  have  `foo=bar'  and `bar=baz', the strings ${(P)foo}, ${(P)${foo}}, and
  ${(P)$(echo bar)} will be expanded to `baz'

एक बार मैंने पढ़ा कि ${${${VAR}}}आप अपेक्षित उत्पादन क्यों नहीं करते हैं, लेकिन इस समय मैं इसे नहीं पा सकता हूं। आप निम्नलिखित की तरह कुछ कर सकते हैं:

first="second" ; second="third" ; third="fourth" ; fourth="fifth"
print ${(P)${(P)${(P)first}}}
fifth

3

आप सही तरीके से eval का उपयोग नहीं कर रहे हैं। आपके उदाहरण में $ VAR के एक "$" (यानी `$ VALUE ') के साथ पहले एक कमांड के रूप में निष्पादित किया जाएगा। वही नहीं जो आप चाहते हैं। आप एक चर के विस्तार का मूल्यांकन करना चाहते हैं जिसका नाम दूसरे चर से लिया गया है।

$ for i in `echo PATH MAIL EDITOR`; 
    do eval moo="\${$i}" 
    echo $moo 
done
/usr/local/sbin:/usr/local/bin:/usr/sbin:/u (...)
/var/mail/root
nano

0

{ba,z}sh समाधान

यहाँ एक फ़ंक्शन है जो {ba, z} sh दोनों में काम करता है। मेरा मानना ​​है कि यह भी POSIX आज्ञाकारी है।

यह दिए जाने पर चेतावनी देता है:

  • अशक्त इनपुट
  • एक से अधिक तर्क
  • एक चर नाम जो सेट नहीं है

# Expand the variable named by $1 into its value. Works in both {ba,z}sh
# eg: a=HOME $(var_expand $a) == /home/me
var_expand() {
  if [ "$#" -ne 1 ] || [ -z "${1-}" ]; then
    printf 'var_expand: expected one non-empty argument\n' >&2;
    return 1;
  fi
  eval printf '%s' "\"\${$1?}\""
}

कोई है functionऔर न ही [[...]]POSIX में sh
स्टीफन चेज़लस

किसी भी तर्क के लिए चेक [ "$#" -eq 0 ](या शायद [ "$#" -ne 1 ]जैसा कि आप केवल एक तर्क की उम्मीद कर रहे हैं) के साथ होना चाहिए ।
स्टीफन चेजलस

@ स्टीफनचेज़ेलस धन्यवाद, अद्यतन। क्या POSIX अनुपालन के लिए एक संदर्भ शेल है? मैं सोच रहा हूँ shell-checkमदद भी कर सकता हूँ ।
टॉम हेल

@ स्टीफनचैलेजेलस ने पुन: परीक्षण किया, मैं यह भी चाहता हूं कि जब एक भी अशक्त तर्क दिया जाए तो मैं विफल होना चाहता हूं। मैंने आपका दूसरा सुझाव जोड़ा है। चीयर्स!
टॉम हेल

मैं == ${1-}दिए गए उद्धरण से सहमत हूं । लेकिन हमेशा एक ही टोकन नहीं होगा ? a='"" -o -n 1' [ -z $a ]0$#
टॉम हेल
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.