केवल लंबे विकल्पों के साथ bash कमांड लाइन में getopt का उपयोग कैसे करें?


13

getoptBash कमांड लाइन में एक कमांड है। getoptछोटे विकल्पों (जैसे कि getopt -o axby "$@") के साथ प्रयोग किया जा सकता है, और छोटे और लंबे दोनों विकल्पों के साथ इस्तेमाल किया जा सकता है (जैसे कि getopt -o axby -l long-key -- "$@"), लेकिन अब मुझे केवल लंबे विकल्प (यानी छोटे विकल्प मौजूद नहीं हैं) की आवश्यकता है, हालांकि कमांड getopt -l long-key -- "$@"नहीं करता है पार्स --long-keyविकल्प सही ढंग से। तो मैं केवल लंबे विकल्पों के getoptसाथ कमांड का उपयोग कैसे कर सकता हूं ? या यह असंभव है या यह सिर्फ कमांड का एक बग है ?getopt


आप आंतरिक के लिए टैग करते हैं getopts, लेकिन आप /usr/bin/getoptकमांड का उपयोग कर रहे हैं ।
एंथन

@Anthon क्षमा करें, मैंने गलत टैग का उपयोग किया है, लेकिन मुझे एक और टैग जोड़ने के लिए पर्याप्त प्रतिष्ठा नहीं मिली है, जिसे 300 प्रतिष्ठा की आवश्यकता है। हालाँकि, मैंने अभी गलत टैग हटा दिया है।
विक्टर

जवाबों:


15

getoptकोई छोटा विकल्प नहीं होने के साथ पूरी तरह से ठीक है। लेकिन आपको यह बताने की जरूरत है कि आपके पास कोई छोटा विकल्प नहीं है। यह सिंटैक्स में एक quirk है - मैनुअल से:

कोई तो -oया --optionsविकल्प पहले भाग में पाया जाता है, दूसरे भाग के पहले पैरामीटर कम विकल्प स्ट्रिंग के रूप में प्रयोग किया जाता है।

आपके परीक्षण में यही हो रहा है: विकल्पों की सूची और एकमात्र तर्क के रूप में getopt -l long-key -- --long-key fooव्यवहार करता है। उपयोग--long-key-egklnoyfoo

getopt -o '' -l long-key -- "$@"

जैसे

$ getopt -l long-key -o '' -- --long-key foo
 --long-key -- 'foo'
$ getopt -l long-key -o '' -- --long-key --not-recognized -n foo
getopt: unrecognized option '--not-recognized'
getopt: invalid option -- 'n'
 --long-key -- 'foo'

क्या आपके जवाब के लिए ओपी का मिश्रण getoptsऔर getoptसंक्रमित था? आप टिप्पणी के साथ शुरू करते हैं getoptsतो केवल उल्लेख करते हैं getopt
एन्थॉन

@Anthon मेरा सारा जवाब getoptGNU कोरुटिल्स के कार्यक्रम के बारे में है जो कि सवाल है। मैंने कहा है कि पाठ तय किया है getopts। धन्यवाद। getoptsलंबे विकल्प भी नहीं करता है, इसलिए इसमें से कोई भी लागू नहीं होगा getopts
गाइल्स का SO- बुराई होना बंद हो '

ओपी मूल रूप से getoptsटैग था। मैं आपके उत्तर को बदलना नहीं चाहता था, क्योंकि आप सामान्य तौर पर जितना जानते हैं उससे बेहतर जानते हैं कि आप :-) के बारे में क्या लिख ​​रहे हैं
एंथॉन

मुझे यह पता लगाने की कोशिश में लगभग एक घंटा खो गया। आपने मुझे कुछ व्यर्थ कॉफी के घूंट पिलाए। धन्यवाद ... इस कॉफ़ी को अब बेहतर उपयोग में लाने की अनुमति देता है। ☕️
dmmd

1

डनो के बारे में, getoptलेकिन getoptsबिलिन का उपयोग इस तरह के केवल लंबे विकल्पों को संभालने के लिए किया जा सकता है:

while getopts :-: o
do  case "$o$OPTARG" in
(-longopt1) process ;;
(-longopt2) process ;;
esac; done

बेशक, जैसा कि है, अगर लंबे विकल्प के तर्क होने चाहिए तो काम नहीं करता। यह किया जा सकता है, हालांकि, लेकिन, जैसा कि मैंने इस पर काम करना सीख लिया है। जबकि मैंने शुरू में इसे यहाँ शामिल किया था मुझे एहसास हुआ कि लंबे समय के विकल्प के लिए इसकी बहुत अधिक उपयोगिता नहीं है। इस मामले में यह केवल case (match)एक एकल, अनुमानित चरित्र द्वारा मेरे क्षेत्रों को छोटा कर रहा था । अब, मुझे जो पता है, वह यह है कि यह छोटे विकल्पों के लिए उत्कृष्ट है - यह सबसे उपयोगी है जब यह अज्ञात लंबाई की एक स्ट्रिंग पर लूप कर रहा है और इसके विकल्प-स्ट्रिंग के अनुसार सिंगल बाइट्स का चयन कर रहा है। लेकिन जब विकल्प है आर्ग, वहाँ आप एक साथ कर रहे हैं एक बहुत नहीं है for var do case $var inसंयोजन यह कर सकता है। यह बेहतर है, मुझे लगता है, इसे सरल रखने के लिए।

मुझे संदेह है कि यह सच है, getoptलेकिन मैं किसी भी निश्चितता के साथ कहने के लिए पर्याप्त नहीं जानता। जो evalation / असाइनमेंट संबंध मैं के लिए सराहना करने के लिए आए हैं पर मुख्य रूप से निर्भर करता है - निम्नलिखित आर्ग सरणी को देखते हुए, मैं अपने खुद के छोटे से आर्ग पार्सर का प्रदर्शन करेंगे aliasऔर $((shell=math))

set -- this is ignored by default --lopt1 -s 'some '\'' 
args' here --ignored   and these are ignored \
--alsoignored andthis --lopt2 'and 

some "`more' --lopt1 and just a few more

यही arg string है जिसके साथ मैं काम करूंगा। अभी:

aopts() { env - sh -s -- "$@"
} <<OPTCASE 3<<\OPTSCRIPT
acase() case "\$a" in $(fmt='
        (%s) f=%s; aset "?$(($f)):";;\n'
        for a do case "$a" in (--) break;;
        (--*[!_[:alnum:]]*) continue;;
        (--*) printf "$fmt" "$a" "${a#--}";;
        esac;done;printf "$fmt" '--*' ignored)
        (*) aset "" "\$a";;esac
shift "$((SHIFT$$))"; f=ignored; exec <&3 
OPTCASE
aset()  {  alias "$f=$(($f${1:-=$(($f))+}1))"
        [ -n "${2+?}" ] && alias "${f}_$(($f))=$2"; }
for a do acase; done; alias
#END
OPTSCRIPT

यह दो अलग-अलग तरीकों में से एक में आर्ग सरणी को संसाधित करता है, इस पर निर्भर करता है कि आप इसे एक या दो सेट के तर्क से अलग करते हैं --। दोनों ही मामलों में यह arg array में प्रोसेसिंग के क्रम पर लागू होता है।

यदि आप इसे कहते हैं:

: $((SHIFT$$=3)); aopts --lopt1 --lopt2 -- "$@"

व्यवसाय का पहला क्रम ऐसा acase()दिखने के लिए अपना कार्य लिखना होगा :

acase() case "$a" in 
    (--lopt1) f=lopt1; aset "?$(($f)):";;
    (--lopt2) f=lopt2; aset "?$(($f)):";;
    (--*) f=ignored; aset "?$(($f)):";;
    (*) aset "" "$a";;esac

और बगल में shift 3acase()फ़ंक्शन परिभाषा में कमांड-प्रतिस्थापन का मूल्यांकन तब किया जाता है जब कॉलिंग शेल फ़ंक्शन-इनपुट को यहां-दस्तावेजों में बनाता है, लेकिन acase()कॉलिंग शेल में कभी भी कॉल या परिभाषित नहीं होता है। यह, हालांकि, निश्चित रूप से, और इस तरह से आप कमांड लाइन पर ब्याज के विकल्प को गतिशील रूप से निर्दिष्ट कर सकते हैं।

यदि आप इसे एक अन-सीमांकित सरणी के रूप में सौंपते हैं तो यह acase()स्ट्रिंग के साथ शुरू होने वाले सभी तर्कों के लिए मेल खाता है --

यह फ़ंक्शन व्यावहारिक रूप से सब-प्रोसेस में सब-शेल में करता है - क्रमिक रूप से सहयोगी नामों के साथ असाइन किए गए उपनामों के प्रत्येक आर्ग के मूल्यों को सहेजना। जब यह इसके माध्यम से होता है तो इसके साथ सहेजे गए हर मूल्य aliasको प्रिंट करता है - जो कि इस तरह से उद्धृत सभी सहेजे गए मूल्यों को प्रिंट करने के लिए POSIX- निर्दिष्ट है ताकि उनके मूल्यों को खोल में फिर से जोड़ा जा सके। इसलिए जब मैं ...

aopts --lopt1 --lopt2 -- "$@"

इसका आउटपुट इस तरह दिखता है:

...ignored...
lopt1='8'
lopt1_1='-s'
lopt1_2='some '\'' args'
lopt1_3='here'
lopt1_4='and'
lopt1_5='just'
lopt1_6='a'
lopt1_7='few'
lopt1_8='more'
lopt2='1'
lopt2_1='and

some "`more'

जैसा कि यह arg सूची के माध्यम से चलता है यह एक मैच के लिए केस ब्लॉक के खिलाफ जांच करता है। यदि यह एक मैच पाता है तो यह एक झंडा फेंकता है - f=optname। जब तक यह एक बार फिर से एक वैध विकल्प नहीं ढूंढता, तब तक यह प्रत्येक बाद के arg को एक सरणी में जोड़ेगा, जो वर्तमान ध्वज के आधार पर बनाता है। यदि एक ही विकल्प कई बार परिणाम यौगिक निर्दिष्ट किया जाता है और ओवरराइड नहीं करता है। मामले में कुछ भी नहीं - या नजरअंदाज विकल्पों के बाद किसी भी तर्क - एक नजरअंदाज सरणी को सौंपा है ।

शेल द्वारा इनपुट-इनपुट स्वचालित रूप से शेल के लिए आउटपुट सुरक्षित है, और इसी तरह:

eval "$(: $((SHIFT$$=3));aopts --lopt1 --lopt2 -- "$@")"

... पूरी तरह से सुरक्षित होना चाहिए। यदि यह किसी भी कारण से सुरक्षित नहीं है , तो आपको संभवतः अपने शेल अनुचर के साथ बग रिपोर्ट दर्ज करनी चाहिए।

यह प्रत्येक मैच के लिए दो प्रकार के अन्य मान प्रदान करता है। सबसे पहले, यह एक ध्वज सेट करता है - यह तब होता है जब कोई विकल्प गैर-मिलान तर्क से पहले होता है या नहीं। --flagअर्ग सूची में कोई भी घटना ट्रिगर हो जाएगी flag=1। यह यौगिक नहीं है - --flag --flag --flagबस हो जाता है flag=1। यह मान हालांकि वृद्धि करता है - किसी भी तर्क के लिए जो इसका पालन कर सकता है। इसका उपयोग इंडेक्स की के रूप में किया जा सकता है। evalऊपर करने के बाद मैं कर सकता हूँ:

printf %s\\n "$lopt1" "$lopt2"

...लेना...

8
1

इसलिए:

for o in lopt1 lopt2
do list= i=0; echo "$o = $(($o))"
        while [ "$((i=$i+1))" -le "$(($o))" ]
        do list="$list $o $i \"\${${o}_$i}\" "
done; eval "printf '%s[%02d] = %s\n' $list";  done

आउटपुट

lopt1 = 8
lopt1[01] = -s
lopt1[02] = some ' args
lopt1[03] = here
lopt1[04] = and
lopt1[05] = just
lopt1[06] = a
lopt1[07] = few
lopt1[08] = more
lopt2 = 1
lopt2[01] = and

some "`more

और यह बताने के लिए कि मैं उपर्युक्त क्षेत्र में नजरअंदाज किए जाने वाले विकल्प से मेल नहीं खाता for ... in:

ignored = 10
ignored[01] = this
ignored[02] = is
ignored[03] = ignored
ignored[04] = by
ignored[05] = default
ignored[06] = and
ignored[07] = these
ignored[08] = are
ignored[09] = ignored
ignored[10] = andthis
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.