Коды результата, объединение в цепочку и флаги
В этой главе рассматривается понятий, связанных с параметрами, что сценарии берут и результаты, которые они возвращают их вызывающей стороне. Это состоит из трех частей:
Работа с Кодами Результата объясняет, что числовой результат кодирует это, сценарии и инструменты возвращаются к сценариям выполнения вызова или инструментам. Это далее объясняет, как сценарии могут использовать те значения, чтобы узнать, успешно выполнился ли инструмент или перестал работать.
Например,
if
оператор иtest
команда сотрудничает к потоку управляющей программы (как описано в Управлении потоком, Расширении, и Анализирующий). Этот раздел объясняет, как это взаимодействие работает под капотом.Объединение в цепочку Выполнения берет понятие кодов результата один шаг вперед, демонстрируя, как можно заставить ряд команд выполниться условно в зависимости от того, успешно выполнились ли предыдущие команды или отказавший.
Обработка Флагов и Параметров говорит, как записать сценарии, берущие сложные флаги и параметры.
Работа с кодами результата
Коды результата, также известные как возвращаемые значения, статусы выхода, и вероятно несколько других имен, являются одной из более критических функций сценариев оболочки, поскольку они играют роль в почти каждом аспекте выполнения сценария.
Каждый раз, когда команда выполняется (включая открытую оболочку скобки, встроенную используемый в качестве части if
и while
операторы), код результата сгенерирован. Если команда выходит успешно, результатом является обычно нуль (0
). Если выходы команды с ошибкой, код результата будет варьироваться согласно инструменту. (См. документацию для рассматриваемого инструмента для списка кодов результата.) Возможный диапазон кодов результата 0-255.
Существует три способа протестировать, чтобы видеть, выполняется ли сценарий правильно. Первое с непосредственным тестом с помощью если оператор. Например:
if ls mysillyfilename ; then |
echo "File exists." |
fi |
Второй путь путем тестирования последнего возвращенного статуса выхода. Статус выхода сохранен в переменной оболочки $?
. Например:
ls mysillyfilename |
if [ $? = 0 ] ; then |
echo "File exists." |
fi |
Третий путь путем использования в своих интересах «и» оператор:
ls mysillyfilename && echo "File exists." |
Эти три примера кода должны генерировать тот же вывод. Третий метод объяснен далее в Объединении в цепочку Выполнения.
Объединение в цепочку выполнения
Оболочка предоставляет трем операторам для объединения в цепочку execution:and (&&
), или (||
) и не (!
).
- И (
&&
) Если команда налево успешно выполняется (имеет нулевой статус выхода), команда вправо выполняется. Иначе, это не делает. Код результата, возвращенный этой работой, является успехом (нуль), только если обе команды возвращают нуль. Иначе, его код результата - то, что было возвращено тем, какой бы ни команда перестала работать.
- Или (
||
) Если команда налево успешно выполняется (имеет нулевой статус выхода), команда вправо не выполняется. Если команда к левым сбоям, вправо выполняется команда. Если крайняя левая команда успешно выполняется, статус выхода, возвращенный этим оператором, является нулем. Иначе, статус выхода возвратился, статус выхода команды направо от оператора.
- Не (
!
) Выполняет команду направо от оператора. Если команда возвращает нулевой статус выхода, оператор возвращает ненулевой статус выхода. Если команда возвращает ненулевой статус выхода, оператор возвращает нулевой статус выхода.
Эти три оператора показаны в следующем отрывке:
ls / || ! ls mysillyfilename && echo "Whatever." |
Правила приоритета оператора в сценариях Оболочки Bourne очень отличаются от тех в C. Круглые скобки оценены сначала, поскольку они могут использоваться для переопределения группировки операторов. После этого, однако, оценка операторов происходит в порядке слева направо.
Например, следующая строка перечисляет все файлы в корневом каталоге, затем отзывается эхом, “Это - мальчик”:
ls / || ls /xy && echo "It's a boy" |
||
оператор имеет приоритет по &&
оператор из-за слева направо правил оценки. Оценка ярлыков оболочки ||
оператор. Таким образом, потому что ls /
всегда успешно выполняется, ||
оператор вызывает второе ls
быть пропущенным полностью, и оператор до &&
оператор оценивает к true
(0
). Это значение тогда объединено с оператором эха после него &&
оператор. Таким образом оператор эха выполняется впоследствии.
Можно изменить порядок операций (или разъяснить его, чтобы избежать смущать людей, не привыкших к языкам без приоритета оператора) путем добавления круглых скобок, как показано в следующем отрывке:
ls / || ( ls /nonexistentfile && echo "file exists" ) |
В этом случае, потому что первое ls
оператор успешен, остаток от оператора пропускается. Если Вы заменяете ls /
с false
, неработающее перечисление nonexistentfile
генерирует сообщение об ошибке и ненулевой статус выхода, поочередно вызывающий echo
оператор, который все еще будет пропущен.
Конечно, существование этих операторов также означает, что Вы могли записать if
оператор, фактически не используя if
ключевое слово, как показано в следующем отрывке:
FOO=3 |
[ $FOO -eq 3 ] && echo "three" |
Поскольку это уменьшает удобочитаемость, однако, этот синтаксис не рекомендуется. Эта форма представлена здесь только для помощи с пониманием существующих сценариев.
Обработка флагов и параметров
Всюду по этой главе и предыдущим главам, примеры показали основную обработку параметра с переменными такой как $1
, $2
, и т.д. Это хорошо для простых сценариев, но некоторого требования сценариев большего количества обработки опережающего аргумента. В этом разделе описываются несколько методов для обработки параметров.
Специальные переменные мультипараметра
Оболочка обеспечивает много специальных переменных, связанных со списками аргументов:
$#
.Содержит число параметров.
$*
.Расширяется до списка параметров, запускающихся с
$1
.Если эта переменная появляется вне двойных кавычек, каждый параметр обрабатывается как единственное неделимое поле в полевых целях разделения. Например, если используется в списке аргументов к команде, каждый исходный параметр передается той команде как отдельный параметр.
Если эта переменная появляется в двойных кавычках, каждый параметр разделяется значением
IFS
переменная и никакое полевое разделение происходят в получающемся блоке. Таким образом, если эта переменная используется в качестве части списка аргументов к команде, это цельноеIFS
- разграниченная строка передается в как отдельный аргумент. Посмотрите Переменное Расширение и Разделителей полей для получения дополнительной информации оIFS
переменная.$@
.Расширяется до списка параметров, запускающихся с
$1
.Если эта переменная появляется вне двойных кавычек, поведение разделения параметра не определяется спецификацией. Однако в большинстве оболочек, текст разделяется, как будто все содержание каждого параметра было вставлено как есть, разделено пробелами, и без любых кавычек.
Если эта переменная появляется в двойных кавычках, каждый параметр обрабатывается как единственное неделимое поле в полевых целях разделения. Таким образом, если эта переменная используется в двойных кавычках в качестве части списка аргументов к команде, каждый исходный параметр передается как отдельный параметр той команде.
Кроме того, если эта переменная появляется в метках двойной кавычки вместе с другим текстом (
"BLAH$@BLAH"
, например), часть строки до$@
предварительно ожидается к первому параметру и части строки после$@
добавляется к последнему параметру.
Следующие листинги кода демонстрируют использование этих параметров и тонких различий между ними.
Перечисление 5-1 00_listargs.sh
#!/bin/sh |
for i in "$@" ; do |
echo ARG $i |
done |
Перечисление 5-2 01_testargs.sh
#!/bin/sh |
IFS=" |
" |
echo "COUNT: $#" |
echo |
echo '\$*' |
./00_listargs.sh $* |
echo |
echo '"\$*"' |
./00_listargs.sh "$*" |
echo |
echo '$@' |
./00_listargs.sh $@ |
echo |
echo '"$@"' |
./00_listargs.sh "$@" |
echo |
echo '"foo bar$*bar foo"' |
./00_listargs.sh "foo bar$*bar foo" |
echo |
echo '"foo bar$@bar foo"' |
./00_listargs.sh "foo bar$@bar foo" |
Сохраните эти сценарии с показанными именами файлов, затем выполните их путем ввода ./01_testargs.sh This is a "silly test"
и отметьте различия в способе, которым ведут себя эти переменные.
Встроенный сдвиг
shift
встроенный обеспечивает способ удалить параметры от списка аргументов. Каждый раз Вы вызываете shift
встроенный, первый параметр удален, и остающиеся параметры смещаются вниз одним. Можно также указать дополнительный числовой параметр для указания, сколько раз Вы хотите сместить список аргументов.
Следующий сценарий демонстрирует встроенный сдвиг:
Перечисление 5-3 02_shift.sh
#!/bin/sh |
echo "\$1: $1 \$2: $2 \$3: $3 \$4: $4 \$5: $5 \$6: $6" |
shift |
echo "\$1: $1 \$2: $2 \$3: $3 \$4: $4 \$5: $5 \$6: $6" |
shift 2 |
echo "\$1: $1 \$2: $2 \$3: $3 \$4: $4 \$5: $5 \$6: $6" |
Выполните этот сценарий путем ввода ./02_shift.sh The quick brown fox jumped over the lazy dog.
и заметьте, как изменяются параметры. Первоначально, первые шесть параметров "The quick brown fox jumped over"
. После первого shift
оператор, первые шесть параметров "quick brown fox jumped over the"
. После второго оператора сдвига первые шесть параметров "fox jumped over the lazy dog"
.
getopts встроенное и getopt команда
getopts
встроенный и getopt
команда оба обрабатывает список параметров способом, который подобен getopt
функция в C. Если Вы пишете сценарий Оболочки Bourne, getopts
встроенный строго рекомендуется, потому что это быстрее, более безопасно, и более гибко. (Если Вы пишете сценарий оболочки C, getopts
встроенный не доступно.)
Оба getopt
и getopts
возьмите строку опции в качестве параметра. Эта строка опции создается следующим образом:
- Простой флаг
Просто используйте букву флага. Например, для добавления
"-f"
отметьте, добавьте букву"f"
к строке опции.- Флаг с параметром
Используйте букву флага, сопровождаемого двоеточием. Например, если Вы хотите принять что-то как
"-o filename"
, Вы добавили бы"o:"
к строке опции.
Как специальная опция, getopts
встроенное обнаружение поддержек неизвестных флагов и недостающих параметров. Для включения этой опции добавьте двоеточие (:
) как первый символ строки опции.
getopts Встроенное
getopts
встроенный помещает Ваш сценарий в управление процесса парсинга параметра. Каждый вызов к getopts
возвращает единственный флаг и, где применимо, параметр тому флагу. Синтаксис следующие:
getopts opt_string user_specified_variable [args] |
Строка опции описана выше в getopts встроенном и getopt команде. Указанная пользователями переменная описана ниже. getopts
встроенный может также дополнительно взять список параметров процессу. Необходимо обычно опускать это.
getopts
встроенный изменяет значения следующих переменных:
- user_specified_variable
Право преимущественной покупки Вы передаете
getopts
имя переменной.getopts
переменная помещает сам флаг в указанную переменную (без ведущего дефиса).OPTARG
Значение аргумента связалось с текущим флагом (если применимо).
OPTERR
В некоторых оболочках, если эта переменная установлена в
1
, сообщение об ошибке базовымgetopt
функция включена. Если установлено в0
, сообщение об ошибке отключено. Это не переносимо, но это относительно безопасно для установки этой переменной «на всякий случай». Эта переменная проигнорирована, если первый символ строки опции является двоеточием (:
), который говоритgetopts
то, что сценарий знает, как обработать и сообщить об ошибках.OPTIND
Индекс текущего обрабатываемого параметра. Необходимо установить это в 1 прежде, чем вызвать
getopts
встроенный впервые (или запускаться, обрабатывая параметры снова с помощью различного набора опций).
Например, следующий сценарий является сырым вариантом ls
команда. Это берет дополнительное -l
флаг, включающий длинные списки и дополнительное -o
флаг, содержащий имя файла, в который это пишет свой вывод. Если никакой выходной файл не указан, это пишет свой вывод в стандартный вывод. Это также берет дополнительный путь или список путей, передающихся ls
как есть.
Перечисление 5-4 03_getopts.sh
#!/bin/sh |
DO_LONG="" |
# Start processing options at index 1. |
OPTIND=1 |
# OPTERR=1 |
OUTPUT_FILE="" |
while getopts ":hlo:" VALUE "$@" ; do |
echo "GOT FLAG $VALUE" |
if [ "$VALUE" = "h" ] ; then |
echo "Usage: $0 [-l] [-o outputfile] [path ...]" |
exit 1 |
fi |
if [ "$VALUE" = "l" ] ; then |
DO_LONG="-l" |
fi |
if [ "$VALUE" = "o" ] ; then |
echo "Set output file to \"$OPTARG\"" |
OUTPUT_FILE="$OPTARG" |
fi |
# The getopt routine returns a colon when it encounters |
# a flag that should have an argument but doesn't. It |
# returns the errant flag in the OPTARG variable. |
if [ "$VALUE" = ":" ] ; then |
echo "Flag -$OPTARG requires an argument." |
echo "Usage: $0 [-l] [-o outputfile] [path ...]" |
exit 1 |
fi |
# The getopt routine returns a question mark when it |
# encounters an unknown flag. It returns the unknown |
# flag in the OPTARG variable. |
if [ "$VALUE" = "?" ] ; then |
echo "Unknown flag -$OPTARG detected." |
echo "Usage: $0 [-l] [-o outputfile] [path ...]" |
exit 1 |
fi |
done |
# The first non-flag argument is at index $OPTIND, so shift one fewer |
# to move it into $1 |
shift `expr $OPTIND - 1` |
if [ "$OUTPUT_FILE" = "" ] ; then |
ls $DO_LONG "$@" |
else |
ls $DO_LONG "$@" > $OUTPUT_FILE |
fi |
exit $? |
Необходимо заметить две вещи об этом сценарии. Во-первых, это использует в своих интересах ведущее двоеточие в строке опции. Это говорит getopts
то, что сценарий знает, как обработать ошибки. Во-вторых, это предоставляет две дополнительных возможности — один для двоеточия (:
) флаг и один для вопросительного знака (?
) флаг. Флаги двоеточия возвращаются когда getopts
встречается с флагом с недостающим параметром. Флаг вопросительного знака возвращается когда getopts
встречается с неизвестным флагом. Эти два дополнительных случая включены ведущим двоеточием в строке опции.
getopt Команда
getopt
команда проявляет другой подход, чем getopts
встроенный. Это обрабатывает весь список аргументов сразу и сообщает, соответствует ли список аргументов список допустимых флагов или нет. Если список аргументов соответствует, getopt
канонизирует список аргументов, помещая флаги и их дополнительные аргументы сначала (до любых параметров нефлага), сопровождаемый синглом "--"
параметр, чтобы указать, что больше нет флагов для обработки.
Синтаксис getopt
команда следующие:
getopt opt_string args |
Следующий отрывок ведет себя во многом как тот в Перечислении 5-4. В отличие от этого в том примере, не возможно программно обнаружить природу ошибок (недостающие параметры или недопустимые флаги).
Кроме того, как отмечено ранее, имена файлов, содержащие пробелы, не обрабатываются правильно getopt
. Это не проблема со сценарием. Это - фундаментальное ограничение getopt
инструмент и путь его вывод анализируются.
Перечисление 5-5 01_getopt.csh
#!/bin/csh |
set OUTPUT_FILE="" |
set DO_LONG="" |
set argv=`getopt "hlo:" $*` |
if ( $status != 0 ) then |
echo "Usage: $0 [-l] [-o outputfile] [path ...]" |
exit 1 |
endif |
while ( "$1" != "--" ) |
echo "GOT FLAG $1" |
switch($1) |
case "-h": |
echo "Usage: $0 [-l] [-o outputfile] [path ...]" |
exit 1 |
case "-o": |
set OUTPUT_FILE="$2" |
shift |
breaksw |
case "-l": |
set DO_LONG="-l" |
breaksw |
endsw |
shift |
end |
shift # remove trailing -- |
# echo "ARGS: $*" |
if ( "$OUTPUT_FILE" == "" ) then |
ls $DO_LONG $* |
else |
ls $DO_LONG $* > $OUTPUT_FILE |
endif |
exit $status |