शेल स्क्रिप्ट्स के लिए नामांकित तर्क पास करना


114

क्या शेल स्क्रिप्ट के लिए नामांकित मापदंडों को पास (प्राप्त) करने का कोई आसान तरीका है?

उदाहरण के लिए,

my_script -p_out '/some/path' -arg_1 '5'

और अंदर my_script.shउन्हें इस रूप में प्राप्त होता है:

# I believe this notation does not work, but is there anything close to it?
p_out=$ARGUMENTS['p_out']
arg1=$ARGUMENTS['arg_1']

printf "The Argument p_out is %s" "$p_out"
printf "The Argument arg_1 is %s" "$arg1"

क्या यह बाश या ज़श में संभव है?


2
डॉकॉप्ट पर एक नज़र डालें - यह नामित मापदंडों के साथ मदद करता है और इनपुट सत्यापन भी करता है
मारो

प्रासंगिक: stackoverflow.com/questions/5499472/…
कज़

जवाबों:


34

संभवत: इसका सबसे निकटतम सिंटैक्स है:

p_out='/some/path' arg_1='5' my_script

7
इससे संबंधित, यदि -kविकल्प कॉलिंग शेल में सेट किया गया है , तो my_script p_out='/some/path' arg_1='5'इसका प्रभाव समान है। (असाइनमेंट के रूप में सभी तर्कों को पर्यावरण में जोड़ा जाता है, न कि केवल उन असाइनमेंट्स जो कमांड से पहले होते हैं।)
chepner

13
मैं इस वाक्यविन्यास से प्यार करता था, लेकिन इसके पास एक बड़ी चेतावनी है: कमांड / फ़ंक्शन निष्पादन के बाद, उन चर को अभी भी वर्तमान दायरे में परिभाषित किया जाएगा! उदा: x=42 echo $x; echo $xजिसका अर्थ है कि अगले निष्पादन में my_script, यदि p_outछोड़ दिया जाता है, तो यह पिछली बार पारित मूल्य से चिपक जाएगा !! ( '/some/path')
लुकास किमोन

@LucasCimon क्या आप unsetउन्हें पहले निष्पादन के बाद नहीं कर सकते , अगले निष्पादन से पहले उन्हें रीसेट कर दें?
निकोस एलेक्जेंड्रिस

2
@LucasCimon यह सही नहीं है। x=42 echo $xकुछ भी आउटपुट नहीं करता है यदि $xपहले परिभाषित नहीं किया गया था।
हौके लैगिंग

आप सही हैं @ हॉकिंग, इसे ठीक करने के लिए धन्यवाद
लुकास

147

आप यानी एकल अक्षर का तर्क नामों को सीमित किया जा रहा कोई आपत्ति नहीं है my_script -p '/some/path' -a5, तो पार्टी में आप इस्तेमाल कर सकते हैं में निर्मित getopts, जैसे

#!/bin/bash

while getopts ":a:p:" opt; do
  case $opt in
    a) arg_1="$OPTARG"
    ;;
    p) p_out="$OPTARG"
    ;;
    \?) echo "Invalid option -$OPTARG" >&2
    ;;
  esac
done

printf "Argument p_out is %s\n" "$p_out"
printf "Argument arg_1 is %s\n" "$arg_1"

तब आप कर सकते हैं

$ ./my_script -p '/some/path' -a5
Argument p_out is /some/path
Argument arg_1 is 5

एक उपयोगी छोटा गेटटॉप ट्यूटोरियल है या आप help getoptsशेल प्रॉम्प्ट पर टाइप कर सकते हैं ।


25
यह स्वीकृत उत्तर होना चाहिए
कौशिक घोष

3
मुझे पता है कि यह थोड़ा पुराना है, लेकिन तर्कों के लिए केवल 1 पत्र ही क्यों?
केविन

1
मैंने इसे लागू किया (लेकिन साथ iऔर d)। जब मैं इसे चलाता हूं तो मुझे तर्क के my_script -i asd -d asdलिए एक खाली स्ट्रिंग मिलती dहै। जब मैं इसे चलाता हूं तो my_script -d asd -i asdमुझे दोनों तर्कों के लिए खाली स्ट्रिंग मिलती है।
मिल्ककुकिएज

3
@Milkncookiez - मुझे एक समान समस्या थी - मैंने अंतिम तर्क (मेरे मामले में एक 'w') के बाद ':' को शामिल नहीं किया। एक बार जब मैंने ':' जोड़ दिया, तो यह उम्मीद के मुताबिक काम करने लगा
डेरेक

37

मैंने इसे drupal.org से चुराया है , लेकिन आप ऐसा कुछ कर सकते हैं:

while [ $# -gt 0 ]; do
  case "$1" in
    --p_out=*)
      p_out="${1#*=}"
      ;;
    --arg_1=*)
      arg_1="${1#*=}"
      ;;
    *)
      printf "***************************\n"
      printf "* Error: Invalid argument.*\n"
      printf "***************************\n"
      exit 1
  esac
  shift
done

एकमात्र चेतावनी यह है कि आपको सिंटैक्स का उपयोग करना होगा my_script --p_out=/some/path --arg_1=5


7
चेतावनी आवश्यक नहीं है। :) आपके पास निम्नानुसार स्थितियां हो सकती हैं:-c|--condition)
मिल्ककुकिएज

28

मैं इस स्क्रिप्ट का उपयोग करता हूं और आकर्षण की तरह काम करता हूं:

for ARGUMENT in "$@"
do

    KEY=$(echo $ARGUMENT | cut -f1 -d=)
    VALUE=$(echo $ARGUMENT | cut -f2 -d=)   

    case "$KEY" in
            STEPS)              STEPS=${VALUE} ;;
            REPOSITORY_NAME)    REPOSITORY_NAME=${VALUE} ;;     
            *)   
    esac    


done

echo "STEPS = $STEPS"
echo "REPOSITORY_NAME = $REPOSITORY_NAME"

प्रयोग

bash my_scripts.sh  STEPS="ABC" REPOSITORY_NAME="stackexchange"

कंसोल परिणाम:

STEPS = ABC
REPOSITORY_NAME = stackexchange

STEPS और REPOSITORY_NAME स्क्रिप्ट में उपयोग करने के लिए तैयार हैं।

इससे कोई फर्क नहीं पड़ता कि तर्क किस क्रम में हैं।


4
यह साफ-सुथरा है और स्वीकृत उत्तर होना चाहिए।
17

15

के साथ zsh, आप उपयोग करेंगे zparseopts:

#! /bin/zsh -
zmodload zsh/zutil
zparseopts -A ARGUMENTS -p_out: -arg_1:

p_out=$ARGUMENTS[--p_out]
arg1=$ARGUMENTS[--arg_1]

printf 'Argument p_out is "%s"\n' "$p_out"
printf 'Argument arg_1 is "%s"\n' "$arg_1"

लेकिन आप स्क्रिप्ट को कॉल करेंगे myscript --p_out foo

ध्यान दें कि zparseoptsसंक्षिप्त विकल्पों का समर्थन नहीं करता है या --p_out=fooGNU जैसे वाक्यविन्यास getopt(3)करता है।


क्या आप जानते हैं कि झपट्ठे ने तर्कों के लिए सिर्फ एक डैश का इस्तेमाल क्यों किया जबकि []इसमें 2 डैश हैं? मतलब नहीं है!
टिमो

@ टिमो, info zsh zparseoptsविवरण के लिए देखें
स्टीफन चेज़लस

9

मैं अभी इस स्क्रिप्ट के साथ आया हूं

while [ $# -gt 0 ]; do

   if [[ $1 == *"--"* ]]; then
        v="${1/--/}"
        declare $v="$2"
   fi

  shift
done

इसे पसंद करें my_script --p_out /some/path --arg_1 5और फिर स्क्रिप्ट में आप उपयोग कर सकते हैं $arg_1और $p_out


केएसएच 88 में मुझे यह समाधान पसंद आया v=``echo ${1} | awk '{print substr($1,3)}'`` typeset $v="$2"(प्रत्येक पक्ष को हटा दें)
होली

-2

यदि किसी फ़ंक्शन या एप्लिकेशन में शून्य से अधिक तर्क हैं, तो इसका हमेशा अंतिम तर्क होता है।

यदि आप विकल्प ध्वज और मूल्य जोड़े पढ़ना चाहते हैं, तो निम्नानुसार: $ ./t.sh -o output -i input -l last

और आप विकल्प / मान जोड़े के एक चर संख्या को स्वीकार करना चाहते हैं,

और एक विशाल "नहीं चाहिए" तो .. और .. फिर "वृक्ष"

फिर गैर-शून्य और यहां तक ​​कि एक तर्क गिनती के लिए जाँच करने के बाद,

बॉडी के रूप में इन चार eval स्टेटमेंट के साथ थोड़ी देर लूप लिखें, इसके बाद केस स्टेटमेंट के साथ लूप के माध्यम से प्रत्येक में निर्धारित दो मानों का उपयोग करें।

पटकथा का मुश्किल हिस्सा यहाँ प्रदर्शित किया गया है:

#!/bin/sh    

# For each pair - this chunk is hard coded for the last pair.
eval TMP="'$'$#"
eval "PICK=$TMP"
eval TMP="'$'$(($#-1))"
eval "OPT=$TMP"

# process as required - usually a case statement on $OPT
echo "$OPT \n $PICK"

# Then decrement the indices (as in third eval statement) 

:<< EoF_test
$ ./t.sh -o output -i input -l last
-l 
last
$ ./t.sh -o output -l last
-l 
last
$ ./t.sh  -l last
-l 
last
EoF_test

-3
mitsos@redhat24$ my_script "a=1;b=mitsos;c=karamitsos"
#!/bin/sh
eval "$1"

आपने स्क्रिप्ट स्कोप के अंदर सिर्फ कमांड लाइन पैरामीटर इंजेक्ट किया है !!


3
यह वाक्य रचना ओपी निर्दिष्ट के साथ काम नहीं करता है; वे चाहते हैं-a 1 -b mitsos -c karamitsos
माइकल Mrozek
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.