मैंने एक समान POSIX फ़ंक्शन लिखा था, लेकिन यह मनमाने ढंग से कोड निष्पादन का जोखिम नहीं उठाता है:
unexport()
while case ${1##[0-9]*} in ### rule out leading numerics
(*[!_[:alnum:]]*|"") ### filter out bad|empty names
set "" ${1+"bad name: '$1'"} ### prep bad name error
return ${2+${1:?"$2"}} ### fail w/ above err or return
esac
do eval set '"$'"{$1+$1}"'" "$'"$1"'" "$'@\" ### $1 = ( $1+ ? $1 : "" )
eval "${1:+unset $1;$1=\$2;} shift 3" ### $$1 = ( $1:+ ? $2 : -- )
done
आप इसे प्रदान करने के लिए देखभाल के रूप में कई तर्कों को भी संभालेंगे। यदि कोई तर्क एक मान्य नाम है जो अन्यथा पहले से सेट नहीं है तो इसे चुपचाप अनदेखा कर दिया जाता है। यदि कोई तर्क एक बुरा नाम है, तो यह उचित रूप में stderr और हाल्ट को लिखता है, हालांकि इसके कमांड-लाइन पर अमान्य से पहले का कोई भी वैध नाम अभी भी संसाधित किया जाएगा।
मैंने दूसरा तरीका सोचा। मुझे यह बहुत अच्छा लगता है।
unexport()
while unset OPTARG; OPTIND=1 ### always work w/ $1
case ${1##[0-9]*} in ### same old same old
(*[!_[:alnum:]]*|"") ### goodname && $# > 0 || break
${1+"getopts"} : "$1" ### $# ? getopts : ":"
return ### getopts errored or ":" didnt
esac
do eval getopts :s: '"$1" -"${'"$1+s}-\$$1\""
eval unset "$1; ${OPTARG+$1=\${OPTARG}#-}"
shift
done
खैर, ये दोनों एक ही तकनीक का भरपूर इस्तेमाल करते हैं। मूल रूप से यदि शेल वर्जन एक संदर्भ है तो यह एक +
पैरामीटर विस्तार के साथ विस्तारित नहीं होगा । लेकिन अगर इसे सेट किया जाता है - भले ही इसके मूल्य की परवाह किए बिना - एक पैरामीटर विस्तार जैसे: ${parameter+word}
का विस्तार होगा word
- और चर के मूल्य तक नहीं। और इसलिए शेल सफलता पर आत्म-परीक्षण और आत्म-विकल्प का परिवर्तन करता है।
वे आत्म-असफल भी हो सकते हैं । शीर्ष फ़ंक्शन में यदि कोई खराब नाम पाया जाता है तो मैं हिल $1
जाता हूं $2
और $1
अशक्त हो जाता हूं क्योंकि अगली चीज जो मैं करता हूं वह return
सफल है यदि सभी आर्ग्स संसाधित किए गए हैं और लूप अंत में है, या, यदि अर्ग अमान्य था, तो शेल होगा उस $2
में विस्तार करें $1:?
जो एक स्क्रिप्टेड शेल को मार देगा और एक इंटरएक्टिव को एक बाधा वापस करेगा जबकि word
स्टडर को लिख रहा है।
दूसरे getopts
में असाइनमेंट करता है। और यह एक बुरा नाम निर्दिष्ट नहीं करेगा - बल्कि यह लिखें कि यह स्टैडर्र को एक मानक त्रुटि संदेश लिख देगा। $OPTARG
यदि तर्क पहले स्थान पर एक सेट चर का नाम था, तो यह और अधिक बचाता है। इतना getopts
सब करने के बाद जो आवश्यक है वह उपयुक्त असाइनमेंट में eval
सेट OPTARG
के विस्तार के लिए है।
mktemp
यदि वह पर्याप्त रूप से पोर्टेबल है, और मान को अनसेट करें, और चर को असाइन करने के लिए अस्थायी फ़ाइल को स्रोत करें। कम से कम एक अस्थायी फ़ाइल शेल चर के विपरीत अधिक या कम मनमाने नाम के साथ बनाई जा सकती है।