2013-02-09 30 views
9

research के कई दिनों के बाद, मैं अभी भी .sh स्क्रिप्ट में cmdline args को पार्स करने के लिए सबसे अच्छी विधि नहीं समझ सकता। मेरे संदर्भ के अनुसार getopts cmd के बाद से यह जाने का रास्ता है "स्थितीय पैरामीटर variables.Unexpected स्विच, या स्विच है कि बहस याद कर रहे हैं को परेशान किए बिना अर्क और चेक स्विच, मान्यता प्राप्त है और त्रुटियों reportedas कर रहे हैं।"बैश में कमांड लाइन का विश्लेषण करने का सबसे अच्छा तरीका है?

स्थितीय पैराम्स (एक्स 2 - $ @, $ #, आदि) स्पष्ट रूप से अच्छी तरह से काम नहीं करते हैं जब रिक्त स्थान शामिल होते हैं लेकिन नियमित और लंबे पैरामीटर (-पी और - लोंगपरम) को पहचान सकते हैं। मैंने देखा कि घोंसला वाले उद्धरणों के साथ पैरामीटर पारित करते समय दोनों विधियां विफल होती हैं ("यह उद्धरण" का एक एक्स है। ")। इन तीन कोड नमूने में से कौन सा सबसे अच्छा cmdline args से निपटने के तरीके को दिखाता है? गेटोप गुरु द्वारा अनुशंसित नहीं है, इसलिए मैं इसे टालने की कोशिश कर रहा हूं!

उदाहरण 1:

#!/bin/bash 
for i in "[email protected]" 
do 
case $i in 
    -p=*|--prefix=*) 
    PREFIX=`echo $i | sed 's/[-a-zA-Z0-9]*=//'` 

    ;; 
    -s=*|--searchpath=*) 
    SEARCHPATH=`echo $i | sed 's/[-a-zA-Z0-9]*=//'` 
    ;; 
    -l=*|--lib=*) 
    DIR=`echo $i | sed 's/[-a-zA-Z0-9]*=//'` 
    ;; 
    --default) 
    DEFAULT=YES 
    ;; 
    *) 
      # unknown option 
    ;; 
esac 
done 
exit 0 

उदाहरण 2:

#!/bin/bash 
echo ‘number of arguments’ 
echo "\$#: $#" 
echo ” 

echo ‘using $num’ 
echo "\$0: $0" 
if [ $# -ge 1 ];then echo "\$1: $1"; fi 
if [ $# -ge 2 ];then echo "\$2: $2"; fi 
if [ $# -ge 3 ];then echo "\$3: $3"; fi 
if [ $# -ge 4 ];then echo "\$4: $4"; fi 
if [ $# -ge 5 ];then echo "\$5: $5"; fi 
echo ” 

echo ‘using [email protected]’ 
let i=1 
for x in [email protected]; do 
echo "$i: $x" 
let i=$i+1 
done 
echo ” 

echo ‘using $*’ 
let i=1 
for x in $*; do 
echo "$i: $x" 
let i=$i+1 
done 
echo ” 

let i=1 
echo ‘using shift’ 
while [ $# -gt 0 ] 
do 
echo "$i: $1" 
let i=$i+1 
shift 
done 

[/bash] 

output: 

bash> commandLineArguments.bash 
number of arguments 
$#: 0 

using $num 
$0: ./commandLineArguments.bash 

using [email protected] 

using $* 

using shift 
#bash> commandLineArguments.bash "abc def" g h i j* 

उदाहरण 3:

#!/bin/bash 

while getopts ":a:" opt; do 
    case $opt in 
    a) 
     echo "-a was triggered, Parameter: $OPTARG" >&2 
     ;; 
    \?) 
     echo "Invalid option: -$OPTARG" >&2 
     exit 1 
     ;; 
    :) 
     echo "Option -$OPTARG requires an argument." >&2 
     exit 1 
     ;; 
    esac 
done 

exit 0 
+1

संभावित डुप्लिकेट [मैं बैश में कमांड लाइन तर्क कैसे पार्स करूं?] (Http://stackoverflow.com/questions/192249/how-do-i-parse-command-line-arguments-in-bash) –

उत्तर

18

मैंके उपयोग को खोजनेसबसे आसान होने के लिए। यह तर्कों का सही संचालन प्रदान करता है जो अन्यथा मुश्किल है। उदाहरण के लिए, getopt कमांड लाइन पर --arg=option या --arg option के रूप में निर्दिष्ट लंबे विकल्प पर तर्कों को संभालने का तरीका जानेंगे।

क्या किसी भी इनपुट एक खोल स्क्रिप्ट के लिए पारित पार्स करने में उपयोगी है "[email protected]" चर का उपयोग है। यह [email protected] से अलग कैसे है के लिए बैश मैन पेज देखें। यह सुनिश्चित करता है कि आप उन तर्कों को संसाधित कर सकते हैं जिनमें रिक्त स्थान शामिल हैं। पता चलता है कि रिक्त स्थान और उद्धरण संरक्षित कर रहे हैं

#!/bin/bash 

args=$(getopt -l "searchpath:" -o "s:h" -- "[email protected]") 

eval set -- "$args" 

while [ $# -ge 1 ]; do 
     case "$1" in 
       --) 
        # No more options left. 
        shift 
        break 
        ;; 
       -s|--searchpath) 
         searchpath="$2" 
         shift 
         ;; 
       -h) 
         echo "Display some help" 
         exit 0 
         ;; 
     esac 

     shift 
done 

echo "searchpath: $searchpath" 
echo "remaining args: $*" 

और इस तरह इस्तेमाल किया:

[email protected]:~/bin$ ./getopt_test --searchpath "File with spaces and \"quotes\"." 
searchpath: File with spaces and "quotes". 
remaining args: other args 

कुछ

यहाँ कैसे मैं रों स्क्रिप्ट लिख सकते हैं कुछ सरल आदेश पंक्ति तर्क पार्स करने के लिए का एक उदाहरण है getopt के उपयोग के बारे में मूलभूत जानकारी here

+2

यह Getopt ऑस्टिन का एक अच्छा उदाहरण है। इस विशेष विषय पर व्यापक रूप से चर्चा की गई है [stackoverflow] (http://stackoverflow.com/questions/402377/using-getopts-in-bash-shell-script-to-get-long-and-short-command-line- विकल्प/7680682 # 7680682)। अंतर सादा पुराना गेटोपेट गेटोपेट्स के रूप में मजबूत नहीं है और पुराने सिस्टम पर काम नहीं करता है। Getopts लंबे स्विच को तब तक पार्स कर सकते हैं जब तक कि एक ही स्विच का एक छोटा संस्करण हो, इसलिए इसे थोड़ी-थोड़ी ट्विकिंग की आवश्यकता होती है। मैं w/getopts छड़ी होगा। मैं पेशेवर स्क्रिप्ट के लिए और पुराने निष्पादन (getopt) के बजाय एक अंतर्निहित फ़ंक्शन का उपयोग करता हूं। – LogicalConfusion

0

यदि आप getopt का उपयोग करने से बचना चाहते हैं तो आप ca n इस अच्छे त्वरित दृष्टिकोण का उपयोग करें:
- ## टिप्पणियों के रूप में सभी विकल्पों के साथ सहायता परिभाषित करना (अपनी इच्छानुसार अनुकूलित करें);
- प्रत्येक विकल्प ही नाम के साथ एक समारोह के लिए परिभाषित करें;
- अपनी स्क्रिप्ट (जादू) के लिए इस स्क्रिप्ट का पिछले पांच लाइनों को कॉपी करें।

उदाहरण: लॉग इन करें।श

#!/bin/sh 
## $PROG 1.0 - Print logs [2017-10-01] 
## Compatible with bash and dash/POSIX 
## 
## Usage: $PROG [OPTION...] [COMMAND]... 
## Options: 
## -i, --log-info   Set log level to info (default) 
## -q, --log-quiet  Set log level to quiet 
## -l, --log MESSAGE  Log a message 
## Commands: 
## -h, --help    Displays this help and exists 
## -v, --version   Displays output version and exists 
## Examples: 
## $PROG -i myscrip-simple.sh > myscript-full.sh 
## $PROG -r myscrip-full.sh > myscript-simple.sh 
PROG=${0##*/} 
LOG=info 
die() { echo [email protected] >&2; exit 2; } 

log_info() { 
    LOG=info 
} 
log_quiet() { 
    LOG=quiet 
} 
log() { 
    [ $LOG = info ] && echo "$1"; return 1 ## number of args used 
} 
help() { 
    grep "^##" "$0" | sed -e "s/^...//" -e "s/\$PROG/$PROG/g"; exit 0 
} 
version() { 
    help | head -1 
} 

[ $# = 0 ] && help 
while [ $# -gt 0 ]; do 
    CMD=$(grep -m 1 -Po "^## *$1, --\K[^= ]*|^##.* --\K${1#--}(?:[= ])" go.sh | sed -e "s/-/_/g") 
    if [ -z "$CMD" ]; then echo "ERROR: Command '$1' not supported"; exit 1; fi 
    shift; eval "$CMD" [email protected] || shift $? 2> /dev/null 
done 

परीक्षण:

./log.sh --log yep --log-quiet -l nop -i -l yes का उत्पादन करेगा:

yep 
yes 

वैसे: यह POSIX के साथ संगत है!