शेल फंक्शंस में स्थानीय चर के दायरे


28

24.2 पढ़ने के बाद स्थानीय चर , मैंने सोचा था कि varकीवर्ड के साथ एक चर घोषित करने का localमतलब है कि varफ़ंक्शन के घुंघराले ब्रेसिज़ द्वारा सीमांकित कोड के ब्लॉक के भीतर केवल मूल्य ही सुलभ था।

हालाँकि, निम्नलिखित उदाहरण को चलाने के बाद, मुझे पता चला कि varकोड के उस ब्लॉक द्वारा आह्वान किए गए फ़ंक्शंस से भी एक्सेस किया जा सकता है, पढ़ा जा सकता है और लिखा जा सकता है - यानी भले ही varघोषित किया localगया हो outerFunc, फिर innerFuncभी इसे पढ़ने और इसके मूल्य में परिवर्तन करने में सक्षम है।

Run It Online

#!/usr/bin/env bash

function innerFunc() {
    var='new value'
    echo "innerFunc:                   [var:${var}]"
}

function outerFunc() {
    local var='initial value'

    echo "outerFunc: before innerFunc: [var:${var}]"
    innerFunc
    echo "outerFunc: after  innerFunc: [var:${var}]"
}

echo "global:    before outerFunc: [var:${var}]"
outerFunc
echo "global:    after  outerFunc: [var:${var}]"

आउटपुट:

global:    before outerFunc: [var:]               # as expected, `var` is not accessible outside of `outerFunc`
outerFunc: before innerFunc: [var:initial value]
innerFunc:                   [var:new value]      # `innerFunc` has access to `var` ??
outerFunc: after  innerFunc: [var:new value]      # the modification of `var` by `innerFunc` is visible to `outerFunc` ??
global:    after  outerFunc: [var:]

प्रश्न: क्या मेरे खोल में एक बग (4.3.42, उबंटू 16.04, 64 बिट) है या यह अपेक्षित व्यवहार है?

संपादित करें: हल किया। जैसा कि @MarkPlotnick ने उल्लेख किया है, यह वास्तव में अपेक्षित व्यवहार है।


यह अपेक्षित व्यवहार है
fpmurphy

2
क्या मैं अकेला हूं जो सोचता है कि यह अजीब है कि आउटपुट की अंतिम पंक्ति में मान का मूल्य varखाली है? varमें विश्व स्तर पर सेट किया गया है innerFunc, तो यह स्क्रिप्ट के अंत तक क्यों नहीं चिपकता है?
हेरोल्ड फिशर

जवाबों:


22

शेल चर में एक गतिशील गुंजाइश होती है । यदि किसी चर को किसी फ़ंक्शन के लिए स्थानीय घोषित किया जाता है, तो फ़ंक्शन वापस आने तक यह गुंजाइश बनी रहती है।

दो अपवाद हैं:

  1. ksh93 में, यदि कोई फ़ंक्शन मानक function_name () { … }सिंटैक्स के साथ परिभाषित किया गया है , तो उसके स्थानीय चर गतिशील स्कोपिंग का पालन करते हैं। लेकिन अगर किसी फ़ंक्शन को ksh सिंटैक्स के साथ परिभाषित किया जाता है, function function_name { … }तो इसका स्थानीय चर lexical / static स्कूपिंग का पालन करता है, इसलिए वे इसके द्वारा बुलाए गए अन्य कार्यों में दिखाई नहीं देते हैं।

  2. zsh/privateमें autoloadable प्लगइन zshएक साथ प्रदान करता है privateकीवर्ड / builtin स्थिर गुंजाइश के साथ एक चर घोषित करने के लिए इस्तेमाल किया जा सकता है।

राख, बाश, पीडीएसएच और डेरिवेटिव, बोश में केवल गतिशील स्कूपिंग है।


क्या शेल के सभी वेरिएबल्स में डायनेमिक स्कोप है या यह केवल घोषित किए गए वेरिएबल्स पर लागू होता है local?
हेरोल्ड फिशर

@ हेरोल्डफिशर सभी चर में गतिशील गुंजाइश होती है। एक साथ typesetया declareया localघोषणा, गुंजाइश समारोह रिटर्न जब तक है। इस तरह की घोषणा के बिना, गुंजाइश वैश्विक है।
गाइल्स 'एसओ- बुराई को रोकना'

6

यह बग नहीं है, आउटरफंक के संदर्भ में कॉल $ वर् की स्थानीय प्रति का उपयोग करता है। आउटरफंच में "लोकल" का मतलब है कि ग्लोबल नहीं बदला है। यदि आप आउटरफंक को आउटरफंक से बाहर कहते हैं, तो वैश्विक $ वर में बदलाव होगा, लेकिन आउटरफंक के स्थानीय $ वर में नहीं। यदि आपने "लोकल" को इनरफंक में जोड़ा है, तो आउटरफंक का $ वर नहीं बदला जाएगा - संक्षेप में, उनमें से 3 होंगे:

  • $ वैश्विक :: वर
  • $ OuterFunc :: वर
  • $ InnerFunc :: वर

पर्ल के नेमस्पेस प्रारूप का उपयोग करने के लिए।


2

आप स्थानीय स्कोप को बाध्य करने के लिए फ़ंक्शन का उपयोग कर सकते हैं:

sh_local() {
  eval "$(set)" command eval '\"\$@\"'
}

उदाहरण:

x() {
  z='new value'
  printf 'function x, z = [%s]\n' "$z"
}
y() {
  z='initial value'
  printf 'function y before x, z = [%s]\n' "$z"
  sh_local x
  printf 'function y after x, z = [%s]\n' "$z"
}
printf 'global before y, z = [%s]\n' "$z"
y
printf 'global after y, z = [%s]\n' "$z"

परिणाम:

global before y, z = []
function y before x, z = [initial value]
function x, z = [new value]
function y after x, z = [initial value]
global after y, z = [initial value]

स्रोत


2

में के रूप में घोषित नहीं किया गया था स्थानीय , इसलिए यह उपलब्ध है दिखाई दायरे में (एक बार समारोह बुलाया गया है)। function innerFunc()var='new value'

इसके विपरीत, में के रूप में घोषित किया गया था स्थानीय , इसलिए यह नहीं वैश्विक क्षेत्र (भले ही समारोह बुलाया गया है) में उपलब्ध है।function outerFunc()local var='initial value'

क्योंकि के innerFunc()एक बच्चे के रूप में कहा जाता था outerFunc(), var स्थानीय दायरे के भीतर है outerFunc()

man 1 bash स्पष्ट करने में मदद मिल सकती है

स्थानीय [विकल्प] [नाम [मूल्य] ...]

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

गर्भित व्यवहार है कि वर्णन में होने की उम्मीद है की घोषणा के द्वारा प्राप्त किया जा सकता local var='new valueमें function innerFunc()

जैसा कि दूसरों ने कहा है, यह बैश शेल में बग नहीं है। सब कुछ कामकाज जैसा कि होना चाहिए।


आपका पहला कथन उपयोगकर्ता जो देख रहा है, उसका खंडन करता है। का मूल्य मुद्रण varवैश्विक क्षेत्र में, बुला के बाद innerFuncके माध्यम से outFunc, प्रिंट नहीं करता new value
Kusalananda
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.