Tôi đã viết một hàm POSIX tương tự, nhưng điều này không có nguy cơ thực thi mã tùy ý:
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
Nó cũng sẽ xử lý nhiều đối số mà bạn quan tâm để cung cấp nó. Nếu một đối số là một tên hợp lệ chưa được đặt khác thì nó sẽ bị bỏ qua một cách âm thầm. Nếu một đối số là một tên xấu, nó ghi vào stderr và tạm dừng là phù hợp, mặc dù bất kỳ tên hợp lệ nào trước một dòng không hợp lệ trên dòng lệnh của nó vẫn sẽ được xử lý.
Tôi nghĩ về một cách khác. Tôi thích nó tốt hơn nhiều.
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
Vâng, cả hai đều sử dụng rất nhiều kỹ thuật giống nhau. Về cơ bản nếu một var shell không được đặt tham chiếu đến nó sẽ không mở rộng với +
việc mở rộng tham số. Nhưng nếu nó được đặt - bất kể giá trị của nó - mở rộng tham số như: ${parameter+word}
sẽ mở rộng thành word
- và không mở rộng giá trị của biến. Và do đó, các biến shell tự kiểm tra và tự thay thế thành công.
Họ cũng có thể tự thất bại . Trong hàm hàng đầu nếu tìm thấy một tên xấu, tôi chuyển $1
sang $2
và để $1
trống vì điều tiếp theo tôi làm là return
thành công nếu tất cả các đối số đã được xử lý và vòng lặp kết thúc hoặc, nếu đối số không hợp lệ, trình bao sẽ không hợp lệ mở rộng $2
vào $1:?
đó sẽ giết chết một cái vỏ được viết kịch bản và trả lại một ngắt cho một cái tương tác trong khi viết word
cho thiết bị lỗi chuẩn.
Trong cái thứ hai getopts
làm bài tập. Và nó sẽ không gán một tên xấu - thay vì viết nó sẽ viết ra một thông báo lỗi tiêu chuẩn cho thiết bị lỗi chuẩn. Hơn thế nữa nó tiết kiệm giá trị của arg trong $OPTARG
nếu đối số là tên của một biến bộ ở nơi đầu tiên. Vì vậy, sau khi làm getopts
tất cả những gì cần thiết là eval
một bộ OPTARG
's mở rộng thành nhiệm vụ thích hợp.
mktemp
nếu nó đủ khả năng di động và bỏ đặt giá trị và lấy nguồn tạm thời để gán biến. Ít nhất một tệp tạm thời có thể được tạo với một tên tùy ý ít nhiều trái ngược với biến shell.