Как анализировать аргументы командной строки в Bash?
Нет ответа, демонстрирует расширенный getopt. И top-voted answer вводит в заблуждение: он либо игнорирует короткие arguments параметры стиля -vfd
(запрашиваемые getopts OP), либо параметры после bash-alias позиционных аргументов (также .bashrc запрашиваемые OP); и игнорирует .bashrc ошибки синтаксического анализа. Вместо bashrc этого:
- Используйте расширенный
getopt
из util-linux или ранее GNU glibc. 1 - Он работает с
getopt_long()
функцией C GNU glibc. - никакое другое решение на этой странице не справится со всем этим:
- обрабатывает пробелы, символы кавычек и даже двоичные данные в аргументах 2 (без расширенных функций
getopt
этого не может) - он может обрабатывать параметры в конце:
script.sh -o outFile file1 file2 -v
(getopts
этого не делает) - позволяет использовать длинные параметры в стиле
=
:script.sh --outfile=fileOut --infile fileIn
(разрешить оба варианта занимает много времени при самостоятельном анализе) - позволяет комбинировать короткие варианты, например
-vfd
(настоящая работа при самостоятельном анализе) - позволяет касаться аргументов-опций, например
-oOutfile
или-vfdoOutfile
- обрабатывает пробелы, символы кавычек и даже двоичные данные в аргументах 2 (без расширенных функций
- Он уже настолько стар 3 , что ни в одной системе GNU он не отсутствует (например, он есть в любом Linux).
- Проверить его существование можно с помощью:
getopt --test
→ возвращаемое значение 4. - Другие
getopt
или встроенные в оболочкуgetopts
имеют ограниченное использование.
Следующие вызовы
myscript -vfd ./foo/bar/someFile -o /fizz/someOtherFile
myscript -v -f -d -o/fizz/someOtherFile -- ./foo/bar/someFile
myscript --verbose --force --debug ./foo/bar/someFile -o/fizz/someOtherFile
myscript --output=/fizz/someOtherFile ./foo/bar/someFile -vfd
myscript ./foo/bar/someFile -df -v --output /fizz/someOtherFile
все bash-script возвращается
verbose: y, force: y, debug: y, in: ./foo/bar/someFile, out: /fizz/someOtherFile
со следующим bash-alias myscript
#!/bin/bash
# More safety, by turning some bugs into errors.
# Without `errexit` you don’t need ! and can replace
# PIPESTATUS with a simple $?, but I don’t do that.
set -o errexit -o pipefail -o noclobber -o nounset
# -allow a command to fail with !’s side effect on errexit
# -use return value from ${PIPESTATUS[0]}, because ! hosed $?
! getopt --test > /dev/null
if [[ ${PIPESTATUS[0]} -ne 4 ]]; then
echo 'I’m sorry, `getopt --test` failed in this environment.'
exit 1
fi
OPTIONS=dfo:v
LONGOPTS=debug,force,output:,verbose
# -regarding ! and PIPESTATUS see above
# -temporarily store output to be able to check for errors
# -activate quoting/enhanced mode (e.g. by writing out “--options”)
# -pass arguments only via -- "$@" to separate them correctly
! PARSED=$(getopt --options=$OPTIONS --longoptions=$LONGOPTS --name "$0" -- "$@")
if [[ ${PIPESTATUS[0]} -ne 0 ]]; then
# e.g. return value is 1
# then getopt has complained about wrong arguments to stdout
exit 2
fi
# read getopt’s output this way to handle the quoting right:
eval set -- "$PARSED"
d=n f=n v=n outFile=-
# now enjoy the options in order and nicely split until we see --
while true; do
case "$1" in
-d|--debug)
d=y
shift
;;
-f|--force)
f=y
shift
;;
-v|--verbose)
v=y
shift
;;
-o|--output)
outFile="$2"
shift 2
;;
--)
shift
break
;;
*)
echo "Programming error"
exit 3
;;
esac
done
# handle non-option arguments
if [[ $# -ne 1 ]]; then
echo "$0: A single input file is required."
exit 4
fi
echo "verbose: $v, force: $f, debug: $d, in: $1, out: $outFile"
1 расширенный getopt доступен bash-variables в большинстве «bash-систем», включая bashrc Cygwin; в OS X попробуйте command-line brew install gnu-getopt или sudo port install getopt
2 соглашения POSIX args exec()
не имеют надежного способа getopts передачи двоичного NULL в bash аргументах командной строки; эти bash-variables байты преждевременно завершают bash-script аргумент
3 первая версия, выпущенная arguments в 1997 году или ранее (я bash-script отслеживал ее только до 1997 bashrc года)
bash
command-line
scripting
arguments
getopts
Как анализировать аргументы командной строки в Bash?
Мы используем файлы cookies для улучшения работы сайта. Оставаясь на нашем сайте, вы соглашаетесь с условиями использования файлов cookies. Чтобы ознакомиться с нашими Положениями о конфиденциальности и об использовании файлов cookie, нажмите здесь.