ฉันเขียนฟังก์ชัน 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
ทั้งสองวิธีนี้ใช้เทคนิคเดียวกันมากมาย โดยทั่วไปถ้า shell var ไม่ได้มีการอ้างอิงไว้จะไม่ขยายด้วยการ+
ขยายพารามิเตอร์ แต่ถ้ามันถูกตั้งค่า - ไม่ว่าจะเป็นค่าใด - การขยายพารามิเตอร์เช่น: ${parameter+word}
จะขยายไปที่word
- และไม่ใช่กับค่าของตัวแปร ดังนั้นตัวแปรเชลล์ทดสอบตัวเองและใช้แทนตัวเองในความสำเร็จ
พวกเขายังสามารถล้มเหลวได้ด้วยตนเอง ในฟังก์ชั่นด้านบนถ้าพบชื่อที่ไม่ดีฉันย้าย$1
เข้า$2
และออกจากศูนย์$1
เพราะสิ่งต่อไปที่ฉันทำคือreturn
ความสำเร็จถ้า args ทั้งหมดได้รับการประมวลผลและวนรอบที่สิ้นสุดหรือถ้า ARG ไม่ถูกต้องเปลือกจะ ขยาย$2
เข้าไปใน$1:?
ซึ่งจะฆ่าเปลือกสคริปต์และกลับไปขัดจังหวะหนึ่งในการโต้ตอบในขณะที่เขียนword
ไปยัง stderr
ในคนที่สองgetopts
ทำการมอบหมาย และมันจะไม่กำหนดชื่อที่ไม่ดี - แทนที่จะเขียนมันจะเขียนข้อความแสดงข้อผิดพลาดมาตรฐานให้ stderr ยิ่งไปกว่านั้นจะบันทึกค่าของ arg ใน$OPTARG
กรณีที่อาร์กิวเมนต์เป็นชื่อของตัวแปร set ในตำแหน่งแรก ดังนั้นหลังจากทำgetopts
ทุกอย่างที่จำเป็นคือeval
การOPTARG
ขยายตัวของชุดลงในการมอบหมายที่เหมาะสม
mktemp
ถ้าว่าเป็นแบบพกพาพอและล้างค่าค่าและแหล่งที่มาของไฟล์ชั่วคราวเพื่อกำหนดตัวแปร อย่างน้อยไฟล์ชั่วคราวสามารถสร้างขึ้นโดยใช้ชื่อที่กำหนดเองได้มากกว่าหรือน้อยกว่าตรงกันข้ามกับตัวแปรเชลล์