getoptі getoptsце різні звірі, і люди, здається, мають трохи нерозуміння того, що роблять. getopts- це вбудована команда для bashобробки параметрів командного рядка в циклі та присвоєння кожному знайденому параметру та значенню по черзі вбудованим змінним, тож ви можете їх далі обробляти. getoptоднак це зовнішня утиліта, і вона насправді не обробляє ваші параметри для вас так, як, наприклад, bash getopts, Perl Getoptмодуль або Python optparse/ argparseмодулі. Все, що потрібно getopt, - це канонізувати параметри, що передаються - тобто перетворити їх у більш стандартну форму, щоб сценарій оболонки був легше обробляти їх. Наприклад, програма getoptможе конвертувати наступне:
myscript -ab infile.txt -ooutfile.txt
в це:
myscript -a -b -o outfile.txt infile.txt
Ви повинні зробити власне обробку самостійно. Вам взагалі не доведеться користуватися, getoptякщо ви робите різні обмеження щодо способу вказівки параметрів:
- поставити лише один варіант на аргумент;
- всі параметри переходять до будь-яких позиційних параметрів (тобто аргументів необов'язкових);
- для параметрів зі значеннями (наприклад,
-oвище) значення має бути окремим аргументом (після пробілу).
Навіщо використовувати getoptзамість getopts? Основна причина полягає в тому, що тільки GNU getoptнадає вам підтримку для давно названих параметрів командного рядка. 1 ( getoptза замовчуванням у Linux є GNU . Mac OS X та FreeBSD поставляються з базовими та не дуже кориснимиgetopt , але версію GNU можна встановити; див. Нижче).
Наприклад, ось приклад використання GNU getoptзі свого скрипту під назвою javawrap:
# NOTE: This requires GNU getopt. On Mac OS X and FreeBSD, you have to install this
# separately; see below.
TEMP=`getopt -o vdm: --long verbose,debug,memory:,debugfile:,minheap:,maxheap: \
-n 'javawrap' -- "$@"`
if [ $? != 0 ] ; then echo "Terminating..." >&2 ; exit 1 ; fi
# Note the quotes around `$TEMP': they are essential!
eval set -- "$TEMP"
VERBOSE=false
DEBUG=false
MEMORY=
DEBUGFILE=
JAVA_MISC_OPT=
while true; do
case "$1" in
-v | --verbose ) VERBOSE=true; shift ;;
-d | --debug ) DEBUG=true; shift ;;
-m | --memory ) MEMORY="$2"; shift 2 ;;
--debugfile ) DEBUGFILE="$2"; shift 2 ;;
--minheap )
JAVA_MISC_OPT="$JAVA_MISC_OPT -XX:MinHeapFreeRatio=$2"; shift 2 ;;
--maxheap )
JAVA_MISC_OPT="$JAVA_MISC_OPT -XX:MaxHeapFreeRatio=$2"; shift 2 ;;
-- ) shift; break ;;
* ) break ;;
esac
done
Це дозволяє вказати варіанти, подібні --verbose -dm4096 --minh=20 --maxhe 40 --debugfi="/Users/John Johnson/debug.txt"або подібні. Ефект заклику до getopt- це канонізувати параметри, щоб --verbose -d -m 4096 --minheap 20 --maxheap 40 --debugfile "/Users/John Johnson/debug.txt"ви могли їх легше обробити. Цитування навколо "$1"і"$2" має важливе значення , оскільки це гарантує , що аргументи з пробілами в них отримати обробляються належним чином.
Якщо ви видалите перші 9 рядків (все вгору через eval setрядок), код все одно буде працювати ! Однак ваш код буде набагато прискіпливішим до того, які варіанти він приймає: Зокрема, вам доведеться вказати всі параметри у "канонічній" формі, описаній вище. За допомогою getopt, однак, ви можете групувати однолітерні параметри, використовувати більш короткі неоднозначні форми довгих опцій, використовувати --file foo.txtабо --file=foo.txtстиль, -m 4096або -m4096стиль, або стиль, змішувати параметри та неопціони в будь-якому порядку тощо. getopt також видає повідомлення про помилку, якщо знайдені нерозпізнані або неоднозначні параметри.
ПРИМІТКА . Насправді є дві абсолютно різні версії getopt, basic getoptта GNU getopt, з різними можливостями та різними умовами виклику. 2 Basic getoptє досить розбитим: він не тільки не обробляє довгі параметри, але навіть не може обробляти вбудовані пробіли всередині аргументів або порожні аргументи, тоді якgetopts робить це правильно. Наведений вище код не буде працювати в базовому getopt. GNU getoptвстановлений за замовчуванням у Linux, але на Mac OS X та FreeBSD його потрібно встановлювати окремо. В Mac OS X встановіть MacPorts ( http://www.macports.org ), а потім зробіть sudo port install getoptінсталяцію GNU getopt(як правило, в /opt/local/bin), і переконайтеся, що /opt/local/binце на шляху вашої оболонки до/usr/bin. На FreeBSD встановіть misc/getopt.
Короткий посібник щодо зміни прикладу коду для вашої власної програми: З перших кількох рядків усі - це "котловарки", які повинні залишатися однаковими, крім лінії, яка дзвонить getopt. Вам слід змінити назву програми після -n, вказати короткі параметри після -oта довгі варіанти після --long. Поставте двокрапку після варіантів, які приймають значення.
Нарешті, якщо ви бачите код, який просто setзамість нього eval set, він був написаний для BSD getopt. Ви повинні змінити його, щоб використовувати eval setстиль, який добре працює з обома версіями getopt, в той час як звичайна setне працює правильно з GNU getopt.
1 Насправді,getopts в ksh93опорах з довгими іменами варіантів, але ця оболонка не використовується так часто , як bash. В zsh, використовувати zparseoptsцю функціональність.
2 Технічно "GNU getopt" - це неправильне значення; ця версія фактично була написана для Linux, а не для проекту GNU. Однак він дотримується всіх конвенцій GNU, і термін "GNU getopt" зазвичай використовується (наприклад, на FreeBSD).