2012-03-26 16 views
19

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

func() { 
    # 
    # Here happens something that ultimately makes $arg="var_name" 
    # 
    declare -g ${arg}=5 
} 

func 

echo ${var_name}; # Prints out "5" 

उपरोक्त कोड स्निपेट बैश 4.2 में शानदार काम करता है। हालांकि, 4.2 से पहले बैश में, declare में -g विकल्प नहीं है। Google पर जो कुछ भी मैंने पाया वह कहता है कि एक फ़ंक्शन के अंदर वैश्विक चर को परिभाषित करने के लिए, मुझे केवल var=value वाक्यविन्यास का उपयोग करना चाहिए, लेकिन दुर्भाग्यवश var स्वयं अन्य चर पर निर्भर करता है। ${arg}=5 काम नहीं करता है, या तो। (यह -bash: var_name=5: command not found कहते हैं।

उत्सुक के लिए, यह सभी के लिए कारण इस समारोह वास्तव में, स्क्रिप्ट मापदंडों से वैश्विक चर बनाता है यानी कि चल script --arg1=val स्वचालित रूप से मूल्य val साथ arg1 नामित चर पैदा करता है। एक बॉयलरप्लेट कोड की टन बचाता है।

+1

आप स्ट्रिंग के रूप में अपना var = value बना सकते हैं और बैश बिल्टिन कमांड 'ev का उपयोग करके इसका मूल्यांकन कर सकते हैं। al'। – minopret

+0

@minopret क्या आप अपनी टिप्पणी को उत्तर के रूप में दोबारा पोस्ट कर सकते हैं? जब तक कि कोई कम हैकिश समाधान के साथ आता है, मैं केवल आपके उत्तर को स्वीकार करूंगा, यह निश्चित रूप से काम करता है। – Leonid99

उत्तर

2

आप स्ट्रिंग के रूप में अपना var = value बना सकते हैं और bash buildin कमांड eval का उपयोग करके इसका मूल्यांकन कर सकते हैं।

+2

जो सरणी के लिए काम नहीं करता है। – sivann

+0

@sivann मेरे उत्तर को देखें – tomy

7

चूंकि यह shell टैग किया गया है, इसलिए यह ध्यान रखना महत्वपूर्ण है कि declare केवल वैध शेल्फ के सीमित सेट में एक वैध कीवर्ड है, इसलिए यह समर्थन करता है -जी मूक है। इस तरह की चीज को सामान्य बॉर्न शैल में करने के लिए, आप केवल eval का उपयोग कर सकते हैं:

eval ${arg}=5 
3

"eval" (या कोई प्रत्यक्ष असाइनमेंट) का उपयोग करके आप विशेष पात्रों (या मूल्य इंजेक्शन आदि के साथ मुद्दों) के साथ सिरदर्द दे सकते हैं।

मैं बस का उपयोग कर "पढ़ें"

$ function assign_global() { 
> local arg="$1" 
> IFS="" read -d "" $arg <<<"$2" 
>} 
$ assign_global MYVAR 23 
echo $MYVAR 
23 
$ assign_global MYVAR "\"'" 
"' 
+0

लेकिन यह चर के लिए एक पिछली नईलाइन जोड़ता है ... –

+0

@gniourf_gniourf - दिया गया उदाहरण वास्तव में नई लाइन जोड़ देगा, लेकिन उदाहरण विशेष रूप से स्ट्रिंग में विशेष वर्णों (जैसे न्यूलाइन) को संबोधित करता है। यदि आप निश्चित हैं कि तर्क को पढ़ने में कोई नई लाइनें नहीं होंगी, तो आप पढ़ने के लिए पढ़ने के लिए -d विकल्प को हटा सकते हैं, लेकिन पहले नए लाइन वर्ण सहित नहीं। –

+0

मुझे लगता है कि यह काम करेगा: 'read -d" \ 0 "$ arg <<<" $ 2 "', 'IFS' – 244an

14

declare अपेक्षा के अनुरूप अंदर एक समारोह काम नहीं करता है बड़ी सफलता मिली है। मुझे फ़ंक्शन में घोषित केवल पढ़ने योग्य वैश्विक चर की आवश्यकता है। मैं एक समारोह के अंदर इस कोशिश की, लेकिन यह काम नहीं किया:

declare -r MY_VAR=1 

लेकिन यह काम नहीं किया। readonly आदेश का उपयोग किया:

func() { 
    readonly MY_VAR=1 
} 
func 
echo $MY_VAR 
MY_VAR=2 

यह 1 प्रिंट और त्रुटि "MY_VAR: केवल पढ़ने के चर" दे देंगे दूसरे काम के लिए।

0

इवल ऐरे चर के साथ काम करेगा ... मुझे केवल स्थानीय एरे वैरिएबल को eval स्टेटमेंट के अंदर उद्धृत करना था।

नीचे एक फ़ाइल में एक फ़ाइल (पहला तर्क) एक पंक्ति में पढ़ता है और उसके बाद get_file के दूसरे तर्क में पारित चर नाम पर प्रतिलिपि बनाता है।

get_file() { 
 
    declare -a Array=(); 
 
    while read line; do 
 
    Array=("${Array[@]}" "($line)") 
 
    done < ${1} 
 
    eval ${2}='("${Array[@]}")' 
 
    unset Array 
 
} 
 

 
declare -a my_array=(); 
 
get_file /etc/myfile.conf my_array 
 
echo ${#my_array[@]}

+0

बदलने की आवश्यकता के बिना, क्या आप 'mapfile' buildin को कार्यान्वित करने की कोशिश कर रहे हैं? 'mapfile -t my_array

+0

दुर्भाग्यवश यह एक सोलारिस 10 एप्लिकेशन के लिए है जो उस बैश कार्यान्वयन में मैपफ़ाइल शामिल नहीं दिखता है। तो इसलिए kludge – ASG

+0

'mapfile' एक बैश बिल्टिन है, इसलिए ओएस अप्रासंगिक है। हालांकि, बैश संस्करण प्रासंगिक है। 'मैपफ़ाइल' संस्करण 4 में दिखाई देता है (जो पहले से ही कुछ साल पुराना है)। –

2

मुझे लगता है कि आप printf अपने -v स्विच के साथ builtin की जरूरत है:

func() { 
    printf -v "$var" '5' 
} 
var=var_name 
func 
echo "$var_name" 

इच्छा उत्पादन 5

0

शायद आप अपने वैश्विक चर को बैश (< 4.2) में गतिशील रूप से असाइन करने के लिए निम्न फ़ंक्शंस का उपयोग कर सकते हैं। यदि> 2 तर्क पास हुए हैं, तो मान सरणी प्रकार होगा। e.g

_set2globals variable_name arg1 [arg2] [arg3] [...] 

स्रोत:

# dynamically set $variable_name($1)=$values($2...) to globals scope 
function _set2globals() 
{ 
    if (($# < 2)); then 
     printf "$FUNCNAME: expect at least 2 argument, but %d you given.\n" $# >&2 
     exit 1 
    fi 
    local ___pattern_='^[_a-zA-Z][_0-9a-zA-Z]*$' 
    if [[ ! $1 =~ $___pattern_ ]]; then 
     printf "$FUNCNAME: invalid variable name: %s.\n" "$1" >&2 
     exit 1 
    fi 
    local __variable__name__=$1 
    shift 
    local ___v_ 
    local ___values_=() 
    while (($# > 0)); do 
     ___v_=\'${1//"'"/"'\''"}\' 
     ___values_=("${___values_[@]}" "$___v_") # push to array 
     shift 
    done 

    eval $__variable__name__=\("${___values_[@]}"\) 
} 
1

आप कुछ चाहते हैं थोड़ा कम hackish, declare -g के स्थान पर export उपयोग करके देखें। इसमें अब पर्यावरण चर होने का अतिरिक्त लाभ है।

func() { 
# 
# Here happens something that ultimately makes $arg="var_name" 
# 
export ${arg}=5 
} 

func 

echo ${var_name}; # Prints out "5" 

दुर्भाग्यवश, यह अभी भी सरणी के लिए काम नहीं करता है।

+0

सरणी निर्यात के साथ काम करने के लिए काम नहीं करेगा, आप मेरा जवाब देख सकते हैं – tomy

0

बैश में एक समारोह परिभाषा के अंदर सरणी चर घोषित करने के लिए आप local आदेश संयोजन में eval कमांड के साथ की तरह निम्न उदाहरण में उपयोग कर सकते हैं:

#!/bin/bash 
function test 
{ 
    local -g $1 
    local array=(AA BB 'C C' DD) 
    eval ${1}='("${array[@]}")' 
} 
test VAR 
echo VAR=${VAR[@]:1:2} 

उत्पादन होगा:

$./test.sh 
VAR=BB C C 

के साथ काम करता है: जीएनयू बैश, संस्करण 4.4.18

संबंधित मुद्दे