मैं शेल स्क्रिप्ट में स्विच कैसे संभाल सकता हूं?


17

क्या कुछ अंतर्निहित उपकरण हैं जो स्विच के रूप में पहचानेंगे -xऔर --xxxxतर्क के रूप में होंगे, या क्या आपको सभी इनपुट चर से गुजरना होगा, डैश के लिए परीक्षण करना होगा, और फिर उसके बाद तर्क को पार्स करना होगा?

जवाबों:


16

का उपयोग करें getopts

यह काफी पोर्टेबल है क्योंकि यह POSIX कल्पना में है। दुर्भाग्य से यह लंबे विकल्पों का समर्थन नहीं करता है।

बैश-हैकर्स विकी के इस getopts ट्यूटोरियल को भी देखें और स्टैकओवरफ़्लो से यह सवाल

यदि आपको केवल छोटे विकल्पों की आवश्यकता है, तो getopts(नॉन-साइलेंट एरर रिपोर्टिंग का उपयोग करके) के लिए विशिष्ट उपयोग पैटर्न है:

# process arguments "$1", "$2", ... (i.e. "$@")
while getopts "ab:" opt; do
    case $opt in
    a) aflag=true ;; # Handle -a
    b) barg=$OPTARG ;; # Handle -b argument
    \?) ;; # Handle error: unknown option or missing required argument.
    esac
done

3
यह उल्लेख किया getoptजाना चाहिए कि हमेशा इसे इस्तेमाल करने से पहले GNU गेटटॉप के रूप में सत्यापित किया जाना चाहिए, लेकिन आपको इसे वैसे भी उपयोग नहीं करना चाहिए जैसा getoptsकि अधिक पोर्टेबल (और आमतौर पर अच्छे) है। यदि आपको इसे किसी कारण से कॉल करने की आवश्यकता है, तो इसे जीएनयू-विशिष्ट तरीके से कॉल करें, और सुनिश्चित करें कि GETOPT_COMPATIBLEयह पर्यावरण में नहीं है।
क्रिस डाउन

बृहदान्त्र क्या करता while getopts "ab:" optहै?
user394

1
@ user394 :विकल्प पत्र के बाद यह दर्शाता है कि उसे एक तर्क की आवश्यकता है। एक :दबाने त्रुटि संदेश के लिए पहली चरित्र साधन के रूप में।
jw013

22

मुझे लगता है कि आप बैश या इसी तरह का उपयोग कर रहे हैं। एक उदाहरण:

all=false
long=false

while getopts ":hal" option; do
  case $option in
    h) echo "usage: $0 [-h] [-a] [-l] file ..."; exit ;;
    a) all=true ;;
    l) long=true ;;
    ?) echo "error: option -$OPTARG is not implemented"; exit ;;
  esac
done

# remove the options from the positional parameters
shift $(( OPTIND - 1 ))

ls_opts=()
$all && ls_opts+=( -a )
$long && ls_opts+=( -l )

# now, do it
ls "${ls_opts[@]}" "$@"

1
+=एक सरणी के साथ उपयोग करने के लिए +1 । नहीं पता था कि आप ऐसा कर सकते हैं। अच्छा!
जेम्स स्नेनरिंग

5

मापदंडों को पार्स करने के लिए आपको एक चक्र लिखना होगा। वास्तव में आप getoptsइसे आसानी से करने के लिए कमांड का उपयोग कर सकते हैं।

यह getoptsमैनुअल पेज से एक सरल उदाहरण है :

aflag=
bflag=
while getopts ab: name
do
    case $name in
    a)    aflag=1;;
    b)    bflag=1
          bval="$OPTARG";;
    ?)    printf "Usage: %s: [-a] [-b value] args\n" $0
          exit 2;;
    esac
done
if [ ! -z "$aflag" ]; then
    printf "Option -a specified\n"
fi
if [ ! -z "$bflag" ]; then
    printf 'Option -b "%s" specified\n' "$bval"
fi
shift $(($OPTIND - 1))
printf "Remaining arguments are: %s\n" "$*"

2

मैंने हाल ही में काम के लिए एक स्क्रिप्ट लिखी थी जो बहुमुखी थी और किसी भी क्रम में कई प्रकार के स्विच के लिए अनुमति दी गई थी। मैं स्पष्ट कानूनी कारणों के लिए पूरी स्क्रिप्ट का खुलासा नहीं कर सकता (उल्लेख करने के लिए नहीं कि मेरे पास फिलहाल मेरे पास नहीं है), लेकिन यहां इसका मांस है .. आप इसे एक सबरूटीन में रख सकते हैं और इसे अंत में कॉल कर सकते हैं आपकी स्क्रिप्ट के अनुसार:

options () {

    if [ -n "$1" ]; then # test if any arguments passed - $1 will always exist
        while (( "$#" )); do  # process ALL arguments
            if [ "$1" = ^-t$ ]; then # -t short for "test"
                # do something here THEN shift the argument
                # shift removes it from $@ and reduces $# by
                # one if you supply no argument
                shift

            # we can also process multiple arguments at once
            elif [[ "$1" =~ ^--test=[:alnum:]{1,8}$ ]] && [[ "$2" =~ ^-t2$ ]] && [[ -n "$3" ]]; then # check for 3 arguments
                # do something more then remove them ALL from the arg list    
                shift 3
            else
                echo "No matching arguments!"
                echo "Usage: [script options list here]"
            fi
        done
    else
        echo "Usage: [script options list here]"
        exit 0
    fi
}

options "$@" # run options and loop through/process ALL arguments

मैं आपकी बैश स्क्रिप्ट को 400 से कम लाइनों / 15k वर्णों तक सीमित करने की सलाह देता हूं; मेरी उक्त स्क्रिप्ट इस आकार से आगे बढ़ी और इस पर काम करना बहुत मुश्किल हो गया। मैंने इसे पर्ल में फिर से लिखना शुरू कर दिया, जो कि कार्य के लिए काफी बेहतर है। इस बात का ध्यान रखें कि आप अपनी स्क्रिप्ट पर काम करें। बैश छोटी स्क्रिप्ट और ओनलीनेर के लिए बहुत अच्छा है, लेकिन कुछ भी अधिक जटिल है और आप इसे पर्ल में लिखना बेहतर समझते हैं।

ध्यान दें, मैंने उपरोक्त परीक्षण नहीं किया है, इसलिए यह संभवतः काम नहीं करता है, लेकिन आपको इससे सामान्य विचार मिलता है।


जिस तरह से आप optionsअंत में कॉल करते हैं वह सही नहीं है, यह वापस आ जाएगा -bash: syntax error near unexpected token $@। यह के रूप में कॉल options "$@"
क्रिस डाउन

हाँ, मैंने पर्ल और बैश को मिलाया। सही किया।
laebshade

इसके बजाय वह whileशर्त नहीं होनी चाहिए (($#))?
मैनावर्क

आपको दो सेट कोष्ठकों की आवश्यकता क्यों होगी $#? संपादित करें: आप सही कह रहे हैं। इसे निर्धारित किया गयाwhile (( "$#" ))
laebshade
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.