2015-02-18 8 views
6

गुजर रहा निम्नलिखित लाइनों (उम्मीद है कि इस सबसे अच्छा अभ्यास है, तो मुझे सही नहीं है कृपया) कमांड लाइन विकल्पों को संभालने के लिए उपयोग करें:बैश - getopts - कमांड लाइन तर्क में बड़े पैमाने पर बहस (ऑपरेंड) पहले स्थान पर

#!/usr/bin/bash 

read -r -d '' HELP <<EOF 
OPTIONS: 
-c Enable color output 
-d Enable debug output 
-v Enable verbose output 
-n Only download files (mutually exclusive with -r) 
-r Only remove files (mutually exclusive with -n) 
-h Display this help 
EOF 

# DECLARE VARIABLES WITH DEFAULT VALUES 
color=0 
debug=0 
verbose=0 
download=0 
remove=0 


OPTIND=1    # Reset in case getopts has been used previously in the shell 
invalid_options=();  # Array for invalid options 

while getopts ":cdvnrh" opt; do 
    echo "Actual opt: $opt" 
    case $opt in 
    c) 
     color=1 
     ;; 
    d) 
     debug=1 
     ;; 
    v) 
     verbose=1 
     ;; 
    n) 
     download=1 
     ;; 
    r) 
     remove=1 
     ;; 
    h) 
     echo "$HELP" 
     exit 1 
     ;; 
    \?) 
     invalid_options+=($OPTARG) 
     ;; 
    *) 
     invalid_options+=($OPTARG) 
     ;; 
    esac 
done 

# HANDLE INVALID OPTIONS 
if [ ${#invalid_options[@]} -ne 0 ]; then 
    echo "Invalid option(s):" >&2 
    for i in "${invalid_options[@]}"; do 
    echo $i >&2 
    done 
    echo "" >&2 
    echo "$HELP" >&2 
    exit 1 
fi 

# SET $1 TO FIRST MASS ARGUMENT, $2 TO SECOND MASS ARGUMENT ETC 
shift $((OPTIND - 1)) 

# HANDLE CORRECT NUMBER OF MASS OPTIONS 
if [ $# -ne 2 ]; then 
    echo "Correct number of mass arguments are 2" 
    echo "" >&2 
    echo "$HELP" >&2 
    exit 1 
fi 


# HANDLE MUTUALLY EXCLUSIVE OPTIONS 
if [ $download -eq 1 ] && [ $remove -eq 1 ]; then 
    echo "Options for download and remove are mutually exclusive" >&2 
    echo "$HELP" >&2 
    exit 1 
fi 



echo "color: $color" 
echo "debug: $debug" 
echo "verbose: $verbose" 
echo "download: $download" 
echo "remove: $remove" 
echo "\$1:  $1" 
echo "\$2:  $2" 

हैं मैं स्क्रिप्ट रास्ता फोन कि mass arguments (उन है कि स्विच या तर्क स्विच के लिए नहीं कर रहे हैं) पिछले तर्क सब कुछ सही ढंग से काम कर रहा है कर रहे हैं:

$ ./getopts.sh -c -d -v -r a b 
Actual opt: c 
Actual opt: d 
Actual opt: v 
Actual opt: r 
color: 1 
debug: 1 
verbose: 1 
download: 0 
remove: 1 
$1:  a 
$2:  b 

समस्या है जब मैं बहुत बड़े पैमाने पर बहस पहले स्थान पर है स्क्रिप्ट कॉल करना चाहते हैं (या कहीं स्विच के बीच में डी ओ तर्क का उपयोग नहीं)

$ ./getopts.sh a b -c -d -v -r 
Correct number of mass arguments are 2 

OPTIONS: 
-c Enable color output 
-d Enable debug output 
-v Enable verbose output 
-n Only download files (mutually exclusive with -r) 
-r Only remove files (mutually exclusive with -d) 
-h Display this help 

या

$ ./getopts.sh -c a b -d -v -r 
Actual opt: c 
Correct number of mass arguments are 2 

OPTIONS: 
-c Enable color output 
-d Enable debug output 
-v Enable verbose output 
-n Only download files (mutually exclusive with -r) 
-r Only remove files (mutually exclusive with -d) 
-h Display this help 

मुझे लगता है कि इस अनुसार ठीक होना चाहिए (इसे POSIX) मानकों, क्योंकि निम्न सिंटैक्स जो मूल रूप से एक ही अपने सिस्टम पर अपेक्षानुसार कार्य कर रही है:

$ cp test1/ test2/ -r 
$ cp test1/ -r test2/ 

मैं इंटरनेट लेकिन केवल बात यह है कि मेरी समस्या के करीब this one सी

से संबंधित था था पर खोज की है
+0

आपके अवलोकन सही हैं: पहली गैर-विकल्प तर्क का सामना करने पर गेटोपेट्स बाहर निकलने की स्थिति लौटाता है, इसलिए जबकि-लूप समाप्त होता है। मेरा मानना ​​है कि ['getopt'] (http://man.cx/getopt) आपके इच्छित अधिक लचीले तरीके से काम कर सकता है। –

+0

@glennjackman getopt पर getopts का उपयोग करने के लिए सिफारिशें हैं। AFAIK Getopt अप्रचलित माना जाता है। –

+0

मुझे विश्वास नहीं है कि Getopt अप्रचलित माना जाता है। गेटोपेट्स का उपयोग करना आसान है (आईएमओ: यह वही है जो मैं उपयोग करता हूं) लेकिन यह आपको आवश्यक पैरामीटर से पहले विकल्पों को रखने के लिए मजबूर करता है और आप - longoptions का उपयोग नहीं कर सकते हैं। –

उत्तर

1

बैश तर्क पार्सिंग के लिए दो विधियां प्रदान करता है।

अंतर्निहित कमांड getopts तर्कों का विश्लेषण करने के लिए एक नया, उपयोग करने में आसान तंत्र है लेकिन यह बहुत लचीला नहीं है। getopts विकल्पों और द्रव्यमान तर्कों को मिश्रण करने की अनुमति नहीं देता है।

बाह्य आदेश getopt तर्कों का विश्लेषण करने के लिए एक पुरानी और अधिक जटिल तंत्र है। यह लंबे/छोटे विकल्प की अनुमति देता है और gnu एक्सटेंशन विकल्पों और द्रव्यमान तर्कों को मिश्रण करने की अनुमति देता है।

3

getopts स्वचालित रूप से जितनी जल्दी हो, जबकि पाश टूट जाता है के रूप में यह एक गैर-पानी का छींटा पैरामीटर ( पैरामीटर तर्क ले पानी का छींटा के लिए दिया तर्क को छोड़कर) का पता लगाता है। POSIX मानक है कि धराशायी पैरामीटर पहले आते हैं, और उसके बाद फ़ाइलें हैं। इसमें -- और + बकवास भी शामिल नहीं है। यह सादा और सरल है।

हालांकि, लिनक्स यूनिक्स या पॉज़िक्स अनुपालन नहीं है। मानक यूनिक्स उपयोगिताओं की तुलना में यह जीएनयू उपयोगिता की प्रकृति में है "बेहतर"। अधिक सुविधाएं, अधिक विकल्प, और चीजों को थोड़ा अलग तरीके से संभालना।

लिनक्स पर, कमांड लाइन पैरामीटर फ़ाइलों के बाद कई जीएनयू उपयोगिताओं में आ सकते हैं।

उदाहरण के लिए: मेरी यूनिक्स प्रमाणित मैक ओएस एक्स पर और लिनक्स पर

$ cp -R foo bar 

कार्य, हालांकि,

$ cp foo bar -R 

केवल लिनक्स पर काम करता है।

यदि आप getopts को कई लिनक्स उपयोगिताओं की तरह काम करने के लिए चाहते हैं, तो आपको बहुत कम काम करने की आवश्यकता है।

सबसे पहले, आपको अपने तर्कों को स्वयं संसाधित करना होगा, और उन्हें पार्स करने के लिए $OPTIND पर निर्भर नहीं होना चाहिए। आपको यह भी सत्यापित करने की आवश्यकता है कि आपके पास तर्क है।

मैं इसे आप जो चाहते हैं उसे करने के उदाहरण के रूप में आया था।

#! /bin/bash 

while [[ $* ]] 
do 
    OPTIND=1 
    echo $1 
    if [[ $1 =~ ^- ]] 
    then 
     getopts :a:b:cd parameter 
     case $parameter in 
      a) echo "a" 
       echo "the value is $OPTARG" 
       shift 
       ;; 
      b) echo "b" 
       echo "the value is $OPTARG" 
       shift 
       ;; 
      c) echo "c" 
       ;; 
      d) echo "d" 
       ;; 
      *) echo "This is an invalid argument: $parameter" 
       ;; 
     esac 
    else 
     other_arguments="$other_arguments $1" 
    fi 
    shift 
done 
echo "$other_arguments" 

मैं अब पाश जब तक $* निर्धारित है। (शायद मुझे [email protected] का उपयोग करना चाहिए?) मुझे लूप के अंत में shift करना है। मैं प्रत्येक बार $OPTIND1 रीसेट करता हूं क्योंकि मैं स्वयं से तर्कों को स्थानांतरित कर रहा हूं। $OPTARG अभी भी सेट है, लेकिन यह सुनिश्चित करने के लिए कि सब कुछ काम करता है, मुझे shift करना होगा।

मुझे यह भी सत्यापित करना होगा कि कोई तर्क डैश के साथ शुरू होता है या मेरे if कथन में नियमित अभिव्यक्ति का उपयोग नहीं करता है।

मूल परीक्षण से पता चलता है कि यह काम करता है, लेकिन मैं यह नहीं कह सकता कि यह त्रुटि मुक्त है, लेकिन यह आपको एक विचार देता है कि आपको अपने कार्यक्रम को कैसे संभालना है।

getopts से आपको अभी भी बहुत सारी शक्ति मिल रही है, लेकिन इसमें थोड़ा और काम लगता है।

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