शैल नामस्थान


10

क्या sourceकिसी नेमस्पेस में शेल स्क्रिप्ट का एक तरीका है , अधिमानतः बैश शेल स्क्रिप्ट है, लेकिन मैं अन्य शेल में देखूंगा यदि उनके पास यह सुविधा है और बैश नहीं है।

मुझे इससे क्या मतलब है, जैसे, "कुछ के साथ सभी परिभाषित प्रतीकों को उपसर्ग जैसा कुछ है ताकि वे पहले से परिभाषित प्रतीकों (चर नाम, फ़ंक्शन नाम, उपनाम)" या किसी अन्य सुविधा से न टकराएं जो नाम टकराव को रोकता है।

यदि कोई समाधान है जहां मैं sourceसमय ( NodeJSशैली) पर नाम रख सकता हूं , तो यह सबसे अच्छा होगा।

उदाहरण कोड:

$ echo 'hi(){ echo Hello, world; }' > english.sh
$ echo 'hi(){ echo Ahoj, světe; }' > czech.sh
$ . english.sh
$ hi
 #=> Hello, world
$ . czech.sh #bash doesn't even warn me that `hi` is being overwritten here
$ hi
 #=> Ahoj, světe
#Can't use the English hi now
#And sourcing the appropriate file before each invocation wouldn't be very efficient 

1
स्पष्टीकरण के लिए धन्यवाद। मुझे उम्मीद है कि उत्तर नकारात्मक है। सामान्य शेल प्रोग्रामिंग प्रतिमान यह है कि जब आप परिवर्तनों को अलग करना चाहते हैं, तो आप इसे एक उप-संस्करण में करते हैं, जो एक बनाने के लिए बस है ( easiest thing ever )। लेकिन यह काफी नहीं है कि आप क्या कर रहे हैं। मुझे लगता है कि आप कर सकते हैं ( stuff in subshell; exec env ) | sed 's/^/namespace_/'और evalमूल शेल में परिणाम है, लेकिन यह बुरा है।
सेलडा

3
हाँ। मिलता है ksh93। नाम स्थान इसके लिए मूलभूत हैं - और इसके सभी प्रकार के नाम (जो टाइप करने योग्य भी हैं) नामस्थान का समर्थन करते हैं। यह व्यावहारिक रूप से हर तरह से बहुत तेज bashहै, वैसे भी।
मौसमी

@mikeserv धन्यवाद, यदि आप इसे एक कोड उदाहरण के साथ उत्तर के रूप में जोड़ते हैं जो कार्यक्षमता को प्रदर्शित करता है, तो मैं इसे स्वीकार करूंगा।
PSkocik

@ प्रतीक मुझे फंक्शन सिंबल और एलियासेस के नामों की भी आवश्यकता होगी। env | sed ...चरों के लिए काम करता है, मैं setफ़ंक्शंस प्राप्त करने के लिए कर सकता हूं , लेकिन खोज और प्रतिस्थापन एक समस्या होगी - फ़ंक्शंस एक-दूसरे को कॉल कर सकते हैं और इसलिए आपको सभी क्रॉस इनवॉक्शंस को प्रीफ़ाइंड क्रॉस इनवॉक्शंस के साथ बदलने की आवश्यकता होगी लेकिन बिना रीप्ले के फ़ंक्शन परिभाषा कोड में कहीं और समान शब्द, जहां यह एक आह्वान नहीं है। उसके लिए आपको बैश पारसर की जरूरत होगी, न कि केवल एक रेगीक्स की, और यह तब भी काम करेगा, जब तक कि फंक्शंस एक दूसरे को इवॉल्व न करें।
PSkocik

जवाबों:


11

से man kshएक के साथ एक सिस्टम पर ksh93स्थापित ...

  • नाम रिक्त स्थान
    • कमांड और फ़ंक्शंस, जिन्हें एक namespaceकमांड की सूची के भाग के रूप में निष्पादित किया जाता है जो चर को संशोधित करते हैं या नए बनाते हैं, एक नया चर बनाते हैं जिसका नाम नाम स्थान का नाम है जैसा कि पहचानकर्ता द्वारा दिया गया है .। जब एक चर जिसका नाम संदर्भित होता है, तो इसे पहली बार उपयोग करने के लिए खोजा जाता है .identifier.name
    • इसी प्रकार, नाम स्थान सूची में एक कमांड द्वारा परिभाषित एक फ़ंक्शन नाम स्थान के नाम का उपयोग करके बनाया गया है .
    • जब किसी नेमस्पेस कमांड की सूची में एक कमांड होती है namespace, तो चर और फ़ंक्शन के नाम जिन्हें बनाया जाता है, जिनमें प्रत्येक के पहले पहचाने गए पहचानकर्ताओं की सूची से पहले वेरिएबल या फ़ंक्शन नाम शामिल होता है .। एक नाम स्थान के बाहर, एक नाम स्थान के अंदर बनाया गया एक चर या फ़ंक्शन इसे नाम स्थान नाम के साथ पूर्ववर्ती द्वारा संदर्भित किया जा सकता है।
    • डिफ़ॉल्ट रूप से, के साथ घूर चर .shमें हैं shनाम अंतरिक्ष।

और, प्रदर्शित करने के लिए, यहां एक शेल्फ़ में असाइन किए गए प्रत्येक नियमित शेल चर के लिए डिफ़ॉल्ट रूप से प्रदान किए गए नाम स्थान पर लागू अवधारणा है ksh93। निम्नलिखित उदाहरण में मैं एक disciplineफ़ंक्शन को परिभाषित करूंगा .getजो $PS1शेल चर के लिए नियत विधि के रूप में कार्य करेगा । हर खोल चर मूल रूप से, के साथ अपने स्वयं के नाम स्थान हो जाता है कम से कम, डिफ़ॉल्ट get, set, append, और unsetतरीकों। निम्नलिखित फ़ंक्शन को परिभाषित करने के बाद, किसी भी समय चर $PS1को शेल में संदर्भित किया जाता है, का उत्पादन dateस्क्रीन के शीर्ष पर तैयार किया जाएगा ...

function PS1.get {
    printf "\0337\33[H\33[K%s\0338" "${ date; }"
}

( ()उपरोक्त कमांड प्रतिस्थापन में उपखंड की कमी पर भी ध्यान दें )

तकनीकी रूप से, नाम स्थान और विषय बिल्कुल एक ही बात नहीं है (क्योंकि विषयों को वैश्विक या स्थानीय रूप से किसी विशेष नाम स्थान पर लागू करने के लिए परिभाषित किया जा सकता है ) , लेकिन वे दोनों शेल डेटा प्रकारों की अवधारणा के लिए भाग और पार्सल हैं जो कि मौलिक हैं ksh93

अपने विशेष उदाहरणों को संबोधित करने के लिए:

echo 'function hi { echo Ahoj, světe\!;  }' >  czech.ksh
echo 'function hi { echo Hello, World\!; }' >english.ksh
namespace english { . ./english.ksh; }
namespace czech   { . ./czech.ksh;   }
.english.hi; .czech.hi

Hello, World!
Ahoj, světe!

... या ...

for ns in czech english
do  ".$ns.hi"
done

Ahoj, světe!
Hello, World!

@PSkocik - आपने मेरी ehoj चीज़ को ठीक क्यों नहीं किया ? मैं शपथ ले सकता था कि यह जो पहले कहा था ... उसके बारे में क्षमा करें। मैंने किसी ऐसे व्यक्ति द्वारा लिखे गए उत्तर को स्वीकार नहीं किया होगा, जो मेरे द्वारा प्रश्न में इस्तेमाल किए गए शब्दों को सही ढंग से लिखने की जहमत नहीं उठा रहा था ... ईमानदारी से, हालांकि, मुझे लगता है कि मुझे याद है कि मैं सिर्फ कॉपी / पेस्ट jt ... hmm ...
mikeserv

2

मैं एक POSIX खोल समारोह जो स्थानीय स्तर पर एक खोल में निर्मित या में से किसी में समारोह नाम स्थान के लिए इस्तेमाल किया जा सकता है लिखा है ksh93, dash, mksh, या bash (विशेष रूप से नामित क्योंकि मैं व्यक्तिगत रूप से इन सभी में काम करने के लिए यह पुष्टि की है) । जिन गोले में मैंने इसका परीक्षण किया, वह केवल मेरी अपेक्षाओं को पूरा करने में विफल yashरहा, और मैंने कभी भी यह उम्मीद नहीं की कि मैं इसमें काम करूंगा zsh। मैंने परीक्षण नहीं किया posh। मैंने poshकुछ समय पहले कोई उम्मीद छोड़ दी है और इसे कुछ समय में स्थापित नहीं किया है। शायद यह में काम करता है posh...?

मैं कहता हूं कि यह POSIX है क्योंकि, विनिर्देश के मेरे पढ़ने से, यह एक बुनियादी उपयोगिता के निर्दिष्ट व्यवहार का लाभ उठाता है, लेकिन, वास्तव में, इस संबंध में विनिर्देश अस्पष्ट है, और, कम से कम एक व्यक्ति जाहिर तौर पर मुझसे असहमत है। आम तौर पर इस बात से मेरी असहमति रही है कि आखिरकार मुझे अपनी गलती मिल गई है, और संभवतः मैं इस बार विनिर्देश के बारे में भी गलत हूं, लेकिन जब मैंने उनसे सवाल किया तो उन्होंने कोई जवाब नहीं दिया।

जैसा कि मैंने कहा, हालांकि, यह निश्चित रूप से पूर्वोक्त गोले में काम करता है, और यह काम करता है, मूल रूप से, निम्नलिखित तरीके से:

some_fn(){ x=3; echo "$x"; }
x=
x=local command eval some_fn
echo "${x:-empty}"

3
empty

commandआदेश एक मूल रूप से उपलब्ध उपयोगिता और पूर्व में से एक के रूप में निर्दिष्ट किया जाता है $PATH'घ builtins। इसके निर्दिष्ट कार्यों में से एक यह है कि इन्हें बनाते समय अपने स्वयं के वातावरण में विशेष निर्मित उपयोगिताओं को लपेटना है, और इसलिए ...

{       sh -c ' x=5 set --; echo "$x"
                x=6 command set --; echo "$x"
                exec <"";  echo uh_oh'
        sh -c ' command exec <""; echo still here'
}

5
5
sh: 3: cannot open : No such file
sh: 1: cannot open : No such file
still here

... ऊपर दोनों कमांड-लाइन असाइनमेंट का व्यवहार कल्पना से सही है। दोनों त्रुटि स्थितियों का व्यवहार भी सही है, और वास्तव में विनिर्देशन से लगभग पूरी तरह से डुप्लिकेट है। वर्तमान शेल वातावरण को प्रभावित करने के लिए फ़ंक्शन या विशेष बिल्डिंस की कमांड-लाइनों के लिए उपसर्ग निर्दिष्ट हैं। इसी तरह, पुनर्निर्देशन त्रुटियों को घातक के रूप में निर्दिष्ट किया जाता है जब उन दोनों में से किसी पर भी इंगित किया जाता है। commandउन मामलों में विशेष निर्मितियों के विशेष उपचार को दबाने के लिए निर्दिष्ट किया जाता है, और पुनर्निर्देशन का मामला वास्तव में विनिर्देश में उदाहरण द्वारा प्रदर्शित होता है।

नियमित रूप से निर्मित, जैसे command, दूसरी ओर, एक उप-वातावरण में चलने के लिए निर्दिष्ट हैं - जो जरूरी नहीं कि एक और प्रक्रिया का मतलब है , बस यह कि यह एक से मौलिक रूप से अप्रभेद्य होना चाहिए। एक नियमित रूप से निर्मित कॉलिंग के परिणाम हमेशा एक समान सक्षम $PATHडी कमांड से प्राप्त किए जा सकते हैं । इसलिए...

na=not_applicable_to_read
na= read var1 na na var2 <<"" ; echo "$var1" "$na" "$var2"
word1 other words word2

word1 not_applicable_to_read word2

लेकिन commandकमांड शेल फ़ंक्शन को कॉल नहीं कर सकता है, और इसलिए इसका उपयोग उनके विशेष उपचार म्यूट को प्रस्तुत करने के लिए नहीं किया जा सकता है क्योंकि यह नियमित बिल्डरों के लिए हो सकता है। यह भी कल्पना है। वास्तव में, युक्ति कहती है कि इसकी एक प्राथमिक उपयोगिता commandयह है कि आप इसे किसी अन्य कमांड के लिए एक रैपर शेल फ़ंक्शन के भीतर उपयोग कर सकते हैं, जो कि अन्य कमांड को स्वयं-पुनरावृत्ति के बिना कॉल करने के लिए है क्योंकि यह फ़ंक्शन को कॉल नहीं करेगा। ऐशे ही:

cd(){ command cd -- "$1"; }

यदि आप commandवहाँ उपयोग नहीं करते हैं तो cdफ़ंक्शन निश्चित रूप से आत्म-पुनरावृत्ति के लिए segfault होगा।

लेकिन एक नियमित बिलिन के रूप में, जो विशेष निर्मित कॉल commandकर सकते हैं, एक उप-वातावरण में ऐसा कर सकते हैं । और हां, तो, जबकि वर्तमान खोल राज्य वर्तमान खोल करने के लिए हो सकता है छड़ी के भीतर परिभाषित - निश्चित रूप से readकी $var1और $var2था - कमांड लाइन परिभाषित करता है की कम से कम परिणाम शायद नहीं करना चाहिए ...

साधारण कमांड

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

अब commandदोनों एक नियमित रूप से निर्मित होने और विशेष निर्मितियों को सीधे कॉल करने की क्षमता है या नहीं , बस कुछ अनपेक्षित कमियां हैं कमांड-लाइन परिभाषित के संबंध में मुझे नहीं पता है, लेकिन मुझे पता है कि कम से कम चार गोले पहले से ही हैं commandनेमस्पेस का सम्मान किया ।

और हालांकि commandसीधे शेल फ़ंक्शन को कॉल नहीं किया जा सकता है, इसे प्रदर्शन के रूप में कॉल कर सकते हैंeval , और इसलिए अप्रत्यक्ष रूप से ऐसा कर सकते हैं। इसलिए मैंने इस कॉन्सेप्ट पर नेमस्पेस रैपर बनाया। यह तर्कों की एक सूची लेता है जैसे:

ns any=assignments or otherwise=valid names which are not a command then all of its args

... सिवाय इसके कि commandऊपर के शब्द को केवल एक के रूप में पहचाना जाता है अगर इसे खाली के साथ पाया जा सकता है $PATH। इसके अलावा कमांड लाइन पर नामित खोल चर स्थानीय रूप से देखते हुए, यह भी इस तरह के रूप एकल लोअर केस वर्णमाला नाम और अन्य मानक वाले की एक सूची, के साथ सभी चर स्थानीय रूप से scopes $PS3, $PS4, $OPTARG, $OPTIND, $IFS, $PATH, $PWD, $OLDPWDऔर कुछ अन्य।

और हाँ, स्थानीय रूप से $PWDऔर $OLDPWDचर और बाद में स्पष्ट रूप से cdआईएनजी द्वारा $OLDPWDऔर $PWDयह काफी मज़बूती से वर्तमान कार्यशील निर्देशिका को भी गुंजाइश कर सकता है। इसकी गारंटी नहीं है, हालांकि यह बहुत कठिन प्रयास करता है। यह एक डिस्क्रिप्टर को बनाए रखता है 7<.और जब इसका रैप टार्गेट रिटर्न करता है cd -P /dev/fd/7/। यदि वर्तमान कार्यशील निर्देशिका unlink()अंतरिम रूप से घ में है, तो भी उसे कम से कम इसे वापस बदलने का प्रबंधन करना चाहिए, लेकिन उस मामले में एक बदसूरत त्रुटि का उत्सर्जन होगा। और क्योंकि यह विवरणक को बनाए रखता है, मुझे नहीं लगता कि एक केन कर्नेल को अपने रूट डिवाइस को या तो अनमाउंट किया जाना चाहिए (???)

यह स्थानीय स्तर पर शेल विकल्प भी देता है, और इनको उस स्थिति में पुनर्स्थापित करता है, जिसमें इसकी लिपटे उपयोगिता के वापस आने पर उन्हें पाया जाता है। यह $OPTSविशेष रूप से व्यवहार करता है कि यह अपने स्वयं के दायरे में एक प्रति रखता है जिसे वह शुरू में मान देता है $-। कमांड-लाइन पर सभी असाइनमेंट को संभालने के बाद यह set -$OPTSअपने रैप लक्ष्य को लागू करने से पहले करेगा । इस तरह यदि आप -$OPTSकमांड-लाइन पर परिभाषित करते हैं तो आप अपने रैप लक्ष्य के शेल विकल्पों को परिभाषित कर सकते हैं। जब लक्ष्य वापस आ जाता है तो set +$- -$OPTSइसकी अपनी प्रति $OPTS (जो कमांड-लाइन डिफाइन से प्रभावित नहीं होती है) और मूल राज्य में सभी को बहाल कर देगा।

बेशक, कॉल returrnटारगेट या उसके तर्कों के माध्यम से फोन करने वाले को किसी भी तरह से स्पष्ट रूप से फ़ंक्शन से बाहर निकलने से रोकना नहीं है। ऐसा करने से किसी भी राज्य की बहाली / सफाई को रोक दिया जाएगा अन्यथा यह प्रयास करेगा।

यह सब करने के लिए तीन evalगहरी जाने की जरूरत है । पहले यह खुद को एक स्थानीय दायरे में लपेटता है, फिर, भीतर से, यह तर्कों में पढ़ता है, उन्हें मान्य शेल नामों के लिए मान्य करता है, और त्रुटि के साथ छोड़ता है अगर यह नहीं मिलता है। यदि सभी तर्क वैध हैं और अंततः एक कारण command -v "$1"सच हो जाता है (याद रखें: $PATHइस बिंदु पर खाली है) तो यह evalकमांड-लाइन को परिभाषित करेगा और रैप टारगेट के सभी शेष तर्कों को पारित करेगा (हालांकि इसके लिए विशेष मामले की अनदेखी करता है ns- क्योंकि वह होगा नहीं 'बहुत उपयोगी है, और तीन evalएस गहरी पर्याप्त से अधिक है)

यह मूल रूप से इस तरह काम करता है:

case $- in (*c*) ... # because set -c doesnt work
esac
_PATH=$PATH PATH= OPTS=$- some=vars \
    command eval LOCALS=${list_of_LOCALS}'
        for a do  i=$((i+1))          # arg ref
              if  [ "$a" != ns ]  &&  # ns ns would be silly
                  command -v "$a" &&
              !   alias "$a"          # aliases are hard to run quoted
        then  eval " PATH=\$_PATH OTHERS=$DEFAULTS $v \
                     command eval '\''
                             shift $((i-1))         # leave only tgt in @
                             case $OPTS in (*different*)
                                  set \"-\${OPTS}\" # init shell opts 
                             esac
                             \"\$@\"                # run simple command
                             set +$- -$OPTS "$?"    # save return, restore opts
                     '\''"
              cd -P /dev/fd/7/        # go whence we came
              return  "$(($??$?:$1))" # return >0 for cd else $1
        else  case $a in (*badname*) : get mad;;
              # rest of arg sa${v}es
              esac
        fi;   done
    ' 7<.

कुछ अन्य पुनर्निर्देशन और, और कुछ अजीब परीक्षण हैं जिस तरह से कुछ गोले डालते cहैं $-और फिर इसे set (???) के विकल्प के रूप में स्वीकार करने से इनकार करते हैं , लेकिन इसका सभी सहायक और मुख्य रूप से सिर्फ उत्सर्जन से बचाने के लिए उपयोग किया जाता है। अवांछित उत्पादन और बढ़त के मामलों में समान है। और इसी तरह यह काम करता है। यह उन चीजों को कर सकता है क्योंकि यह अपने लपेटे हुए उपयोगिता को एक नेस्टेड में कॉल करने से पहले अपना स्थानीय दायरा सेट करता है।

यह लंबा है, क्योंकि मैं यहां बहुत सावधान रहने की कोशिश करता हूं - तीन evalsकठिन है। लेकिन इसके साथ आप यह कर सकते हैं:

ns X=local . /dev/fd/0 <<""; echo "$X" "$Y"
X=still_local
Y=global
echo "$X" "$Y"

still_local global
 global

लिपटे उपयोगिता के स्थानीय स्कोप को लगातार आगे बढ़ाते हुए नाम देना बहुत कठिन नहीं होना चाहिए। और यहां तक ​​कि जैसा कि लिखा गया है, यह पहले $LOCALSसे ही लिपटे उपयोगिता के लिए एक चर को परिभाषित करता है जो सभी नामों की केवल एक अलग-अलग सूची से मिलकर बनता है जो इसे लिपटे उपयोगिता के वातावरण में परिभाषित करता है।

पसंद:

ns var1=something var2= eval ' printf "%-10s%-10s%-10s%s\n" $LOCALS '

... जो पूरी तरह से सुरक्षित है - $IFSइसे अपने डिफ़ॉल्ट मूल्य के लिए पवित्रा कर दिया गया है और केवल वैध शेल नाम इसे बनाते हैं $LOCALSजब तक कि आप इसे स्वयं कमांड लाइन पर सेट न करें। और यहां तक ​​कि अगर एक विभाजित चर में ग्लोब वर्ण हो सकते हैं, तो आप OPTS=fअपने विस्तार को प्रतिबंधित करने के लिए लिपटे उपयोगिता के लिए कमांड-लाइन पर भी सेट कर सकते हैं । किसी भी स्थिति में:

LOCALS    ARG0      ARGC      HOME
IFS       OLDPWD    OPTARG    OPTIND
OPTS      PATH      PS3       PS4
PWD       a         b         c
d         e         f         g
h         i         j         k
l         m         n         o
p         q         r         s
t         u         v         w
x         y         z         _
bel       bs        cr        esc
ht        ff        lf        vt
lb        dq        ds        rb
sq        var1      var2      

और यहाँ फ़ंक्शन है। विस्तार \से बचने के लिए सभी कमांड्स पूर्वनिर्मित w / हैं alias:

ns(){  ${1+":"} return
       case  $- in
       (c|"") ! set "OPTS=" "$@"
;;     (*c*)  ! set "OPTS=${-%c*}${-#*c}" "$@"
;;     (*)      set "OPTS=$-" "$@"
;;     esac
       OPTS=${1#*=} _PATH=$PATH PATH= LOCALS=     lf='
'      rb=\} sq=\' l= a= i=0 v= __=$_ IFS="       ""
"      command eval  LOCALS=\"LOCALS \
                     ARG0 ARGC HOME IFS OLDPWD OPTARG OPTIND OPTS     \
                     PATH PS3 PS4 PWD a b c d e f g h i j k l m n     \
                     o p q r s t u v w x y z _ bel bs cr esc ht ff    \
                     lf vt lb dq ds rb sq'"
       for a  do     i=$((i+1))
              if     \[ ns != "$a" ]         &&
                     \command -v "$a"  >&9   &&
              !      \alias "${a%%=*}" >&9 2>&9
              then   \eval 7>&- '\'    \
                     'ARGC=$((-i+$#))  ARG0=$a      HOME=~'           \
                     'OLDPWD=$OLDPWD   PATH=$_PATH  IFS=$IFS'         \
                     'OPTARG=$OPTARG   PWD=$PWD     OPTIND=1'         \
                     'PS3=$PS3 _=$__   PS4=$PS4     LOCALS=$LOCALS'   \
                     'a= b= c= d= e= f= g= i=0 j= k= l= m= n= o='     \
                     'p= q= r= s= t= u= v= w= x=0 y= z= ht=\   '      \
                     'cr=^M bs=^H ff=^L vt=^K esc=^[ bel=^G lf=$lf'   \
                     'dq=\" sq=$sq ds=$ lb=\{ rb=\}' \''"$v'          \
                            '\command eval       9>&2 2>&- '\'        \
                                   '\shift $((i-1));'                 \
                                   'case \${OPTS##*[!A-Za-z]*} in'    \
                                   '(*[!c$OPTS]*) >&- 2>&9"'\'        \
                                   '\set -"${OPTS%c*}${OPTS#*c}"'     \
                                   ';;esac; "$@" 2>&9 9>&-; PS4= '    \
                                   '\set  +"${-%c*}${-#*c}"'\'\"      \
                                          -'$OPTS \"\$?\"$sq";'       \
              '             \cd -- "${OLDPWD:-$PWD}"
                            \cd -P  ${ANDROID_SYSTEM+"/proc/self/fd/7"} /dev/fd/7/
                            \return "$(($??$?:$1))"
              else   case   ${a%%=*}      in
                     ([0-9]*|""|*[!_[:alnum:]]*)
                            \printf "%s: \${$i}: Invalid name: %s\n" \
                            >&2    "$0: ns()"   "'\''${a%%=*}'\''"
                            \return 2
              ;;     ("$a") v="$v $a=\$$a"
              ;;     (*)    v="$v ${a%%=*}=\${$i#*=}"
              ;;     esac
                     case " $LOCALS " in (*" ${a%%=*} "*)
              ;;     (*)    LOCALS=$LOCALS" ${a%%=*}"
              ;;     esac
              fi
       done'  7<.    9<>/dev/null
}

बहुत चालाक! इसी तरह के पैटर्न का उपयोग यहाँ बहुत कुछ हासिल करने के लिए किया जाता है: github.com/stephane-chazelas/misc-scripts/blob/master/locvar.sh
Zac B
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.