Я написав подібну функцію 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
Що ж, обидва використовують багато одних і тих же прийомів. В основному, якщо var shell не встановлено, посилання на нього не розширюватиметься при +
розширенні параметра. Але якщо він встановлений - незалежно від його значення - розширення параметра типу: ${parameter+word}
розшириться на word
-, а не на значення змінної. І так змінні оболонки самоперевіряються та самозамінюються на успіх.
Вони також можуть зазнати невдач . У функції верхньої , якщо погане ім'я знайдене я рухаюся $1
в $2
і відпустці $1
порожній , тому що наступна річ , яку я роблю, або return
успіх , якщо всі аргументи були оброблені і петля на кінці, або, якщо аргумент є недійсним, то оболонка розширення, $2
в $1:?
яке буде вбито сценарій оболонки і повернеться переривання в інтерактивний при написанні word
в stderr.
У другому getopts
виконують завдання. І це не призначить поганого імені - скоріше напишіть, що воно випише стандартне повідомлення про помилку в stderr. Більше того, це зберігає значення arg, $OPTARG
якщо аргументом в першу чергу було ім'я змінної набору. Отже після виконання getopts
всього необхідного є eval
розширення набору OPTARG
у відповідне завдання.
mktemp
якщо що є портативним досить, і скинути значення, і джерело тимчасовий файл для присвоєння змінної. Принаймні тимчасовий файл може бути створений з більш-менш довільним іменем на відміну від змінної оболонки.