मैं बिना मूल्य खोए, एक चर को कैसे निर्यात कर सकता हूं?


10

मान लीजिए कि मैंने एक चर निर्यात किया है:

foo=bar
export foo

अब, मैं इसका निर्यात करना चाहूंगा। यही कारण है कि कहने के लिए है, तो मुझे क्या करना है, sh -c 'echo "$foo"'मैं नहीं करना चाहिए barfooबिल्कुल भी नहीं दिखाना चाहिए sh -csh -cएक उदाहरण है, एक चर की उपस्थिति दिखाने का एक आसान तरीका है। कमांड कुछ भी हो सकता है - यह कुछ ऐसा हो सकता है जिसका व्यवहार केवल इसके वातावरण में चर की उपस्थिति से प्रभावित होता है।

हाँ मैं:

  1. unset चर, और इसे खो देते हैं
  2. envप्रत्येक आदेश के लिए इसे निकालें :env -u foo sh -c 'echo "$foo"'
    • अव्यवहारिक यदि आप कुछ समय के लिए वर्तमान शेल का उपयोग जारी रखना चाहते हैं।

आदर्श रूप से, मैं चर का मूल्य रखना चाहूंगा, लेकिन यह एक बच्चे की प्रक्रिया में बिल्कुल भी नहीं दिखा, न कि एक खाली चर के रूप में।

मुझे लगता है कि मैं कर सकता था:

otherfoo="$foo"; unset foo; foo="$otherfoo"; unset otherfoo

otherfooयदि यह पहले से मौजूद है, तो यह खतरे में पड़ जाता है।

क्या यह एकमात्र तरीका है? क्या कोई मानक तरीके हैं?


1
आप किसी अस्थायी फ़ाइल में मान को प्रतिध्वनित कर सकते हैं, mktempयदि वह पर्याप्त रूप से पोर्टेबल है, और मान को अनसेट करें, और चर को असाइन करने के लिए अस्थायी फ़ाइल को स्रोत करें। कम से कम एक अस्थायी फ़ाइल शेल चर के विपरीत अधिक या कम मनमाने नाम के साथ बनाई जा सकती है।
थॉमस डिके

@Sukminder sh -cकमांड केवल एक उदाहरण है। ऐसा कोई भी आदेश लें जिसके भीतर आप किसी चर को उसके स्थान पर न जोड़ सकें, यदि आप करेंगे।
मुरु

जवाबों:


6

कोई मानक तरीका नहीं है।

आप एक फ़ंक्शन का उपयोग करके एक अस्थायी चर का उपयोग करने से बच सकते हैं। निम्नलिखित फ़ंक्शन को ध्यान देने योग्य वेरिएबल्स को परेशान करने और खाली चर को खाली रखने के लिए ध्यान रखता है। हालाँकि यह कुछ शेल में पायी जाने वाली सुविधाओं जैसे कि केवल-पढ़ने या टाइप किए गए चर का समर्थन नहीं करता है।

unexport () {
  while [ "$#" -ne 0 ]; do
    eval "set -- \"\${$1}\" \"\${$1+set}\" \"\$@\""
    if [ -n "$2" ]; then
      unset "$3"
      eval "$3=\$1"
    fi
    shift; shift; shift
  done
}
unexport foo bar

Ksh, bash और zsh में, आप किसी वैरिएबल को अनएक्सपोर्ट कर सकते हैं typeset +x foo। यह विशेष गुणों को संरक्षित करता है जैसे कि प्रकार, इसलिए इसका उपयोग करना बेहतर होता है। मुझे लगता है कि सभी गोले जो एक typesetबेसिन है typeset +x

case $(LC_ALL=C type typeset 2>&1) in
  typeset\ *\ builtin) unexport () { typeset +x -- "$@"; };;
  *) unexport () {  };; # code above
esac

1
उन अपरिचित लोगों के लिए ${var+foo}, यह निर्धारित करता है fooकि varक्या सेट किया गया है, भले ही खाली हो, और अन्यथा कुछ भी नहीं।
मुरु

कहो, आप पर कोई टिप्पणी करना typeset +xबनाम export -nगोले पूर्व का समर्थन करते हैं कि के लिए? क्या export -nदुर्लभ है, या यह कुछ गुणों को संरक्षित नहीं करता है?
मुरु

@ एमआरयू यदि आप एक बैश स्क्रिप्ट लिख रहे हैं, तो आप उपयोग export -nया typeset +xउदासीनता से कर सकते हैं । Ksh या zsh में, केवल है typeset +x
गिल्स का SO- '

7

संपादित करें: के लिए bashकेवल, के रूप में टिप्पणी में कहा:

-nकरने का विकल्प exportहटा देगा exportप्रत्येक व्यक्ति का नाम से संपत्ति। (देखें help export।)

तो के लिए bash, आदेश आप चाहते है:export -n foo


1
यह शेल-विशिष्ट है ( POSIX देखें ), ओपी ने एक शेल निर्दिष्ट नहीं किया, लेकिन समस्या को हल करने का एक मानक तरीका पूछा ।
थॉमस डिके

1
@ThomasDickey, उस के बारे में पता नहीं था। धन्यवाद, अद्यतन।
वाइल्डकार्ड

3

मैंने एक समान POSIX फ़ंक्शन लिखा था, लेकिन यह मनमाने ढंग से कोड निष्पादन का जोखिम नहीं उठाता है:

unexport()
    while case ${1##[0-9]*} in                   ### rule out leading numerics
          (*[!_[:alnum:]]*|"")                   ### filter out bad|empty names
          set "" ${1+"bad name: '$1'"}           ### prep bad name error
          return ${2+${1:?"$2"}}                 ### fail w/ above err or return 
          esac
    do    eval  set '"$'"{$1+$1}"'" "$'"$1"'" "$'@\" ###  $1 = (  $1+ ? $1 : "" )
          eval  "${1:+unset $1;$1=\$2;} shift 3"     ### $$1 = ( $1:+ ? $2 : -- )
    done

आप इसे प्रदान करने के लिए देखभाल के रूप में कई तर्कों को भी संभालेंगे। यदि कोई तर्क एक मान्य नाम है जो अन्यथा पहले से सेट नहीं है तो इसे चुपचाप अनदेखा कर दिया जाता है। यदि कोई तर्क एक बुरा नाम है, तो यह उचित रूप में stderr और हाल्ट को लिखता है, हालांकि इसके कमांड-लाइन पर अमान्य से पहले का कोई भी वैध नाम अभी भी संसाधित किया जाएगा।

मैंने दूसरा तरीका सोचा। मुझे यह बहुत अच्छा लगता है।

unexport()
        while   unset OPTARG; OPTIND=1           ### always work w/ $1
                case  ${1##[0-9]*}    in         ### same old same old
                (*[!_[:alnum:]]*|"")             ### goodname && $# > 0 || break
                    ${1+"getopts"} : "$1"        ### $# ? getopts : ":"
                    return                       ### getopts errored or ":" didnt
                esac
        do      eval   getopts :s: '"$1" -"${'"$1+s}-\$$1\""
                eval   unset  "$1;  ${OPTARG+$1=\${OPTARG}#-}"
                shift
        done

खैर, ये दोनों एक ही तकनीक का भरपूर इस्तेमाल करते हैं। मूल रूप से यदि शेल वर्जन एक संदर्भ है तो यह एक +पैरामीटर विस्तार के साथ विस्तारित नहीं होगा । लेकिन अगर इसे सेट किया जाता है - भले ही इसके मूल्य की परवाह किए बिना - एक पैरामीटर विस्तार जैसे: ${parameter+word}का विस्तार होगा word- और चर के मूल्य तक नहीं। और इसलिए शेल सफलता पर आत्म-परीक्षण और आत्म-विकल्प का परिवर्तन करता है।

वे आत्म-असफल भी हो सकते हैं । शीर्ष फ़ंक्शन में यदि कोई खराब नाम पाया जाता है तो मैं हिल $1जाता हूं $2और $1अशक्त हो जाता हूं क्योंकि अगली चीज जो मैं करता हूं वह returnसफल है यदि सभी आर्ग्स संसाधित किए गए हैं और लूप अंत में है, या, यदि अर्ग अमान्य था, तो शेल होगा उस $2में विस्तार करें $1:?जो एक स्क्रिप्टेड शेल को मार देगा और एक इंटरएक्टिव को एक बाधा वापस करेगा जबकि wordस्टडर को लिख रहा है।

दूसरे getoptsमें असाइनमेंट करता है। और यह एक बुरा नाम निर्दिष्ट नहीं करेगा - बल्कि यह लिखें कि यह स्टैडर्र को एक मानक त्रुटि संदेश लिख देगा। $OPTARG यदि तर्क पहले स्थान पर एक सेट चर का नाम था, तो यह और अधिक बचाता है। इतना getoptsसब करने के बाद जो आवश्यक है वह उपयुक्त असाइनमेंट में evalसेट OPTARGके विस्तार के लिए है।


2
इन दिनों में से एक, मैं आपका जवाब देने के लिए अपने सिर को लपेटने की कोशिश करने के बाद मनोरोग वार्ड में जाऊंगा। : डी कैसे अन्य जवाब मनमाने कोड निष्पादन से ग्रस्त है? क्या आप एक उदाहरण प्रदान कर सकते हैं?
मुरु

3
@ एमरू - जब तक कि कोई तर्क अमान्य नाम नहीं है। लेकिन यह समस्या नहीं है - समस्या यह है कि इनपुट मान्य नहीं है। हां, यह आवश्यक है कि आप इसे एक अजीब नाम के साथ एक तर्क दें, ताकि इसे मनमाने कोड पर अमल किया जा सके - लेकिन यह इतिहास में हर सीवीई के लिए बहुत आधार है। यदि आप exportएक अजीब नाम की कोशिश करते हैं , तो यह आपके कंप्यूटर को नहीं मारेगा।
मोकेसर

1
@ मुरु - ओह, और तर्क मनमानी हो सकते हैं: var=something; varname=var; export "$varname"पूरी तरह से वैध है। वही इसके लिए unsetऔर इस के साथ और अन्य के लिए चला जाता है , लेकिन जिस मिनट में उस "$varname"चर की सामग्री पागल हो जाती है, यह अफसोसजनक हो सकता है। और यह बहुत अच्छा है कि पूरे bashसमारोह निर्यात पराजय वैसे भी कैसे हुआ।
मोकेसर

1
@ mikeserv मुझे लगता है कि आप बहुत अधिक अपवोट (कम से कम मुझसे) प्राप्त करेंगे यदि आपने उस ओबफैक्टेड कोड को उस कोड से बदल दिया जो खुद को समझाता है (या कम से कम टिप्पणी करता है)
PSkocik

1
@PSkocik - किया गया।
मोकेसर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.