Метод № 1: Использование bash без getopt [s]
Два распространенных способа передачи аргументов пары ключ-значение:
Разделенный пробелами (например, --option argument
) (без getopt [s])
Использование ./myscript.sh -e conf -s /etc -l /usr/lib /etc/hosts
#!/bin/bash
POSITIONAL=()
while [[ $# -gt 0 ]]
do
key="$1"
case $key in
-e|--extension)
EXTENSION="$2"
shift # past argument
shift # past value
;;
-s|--searchpath)
SEARCHPATH="$2"
shift # past argument
shift # past value
;;
-l|--lib)
LIBPATH="$2"
shift # past argument
shift # past value
;;
--default)
DEFAULT=YES
shift # past argument
;;
*) # unknown option
POSITIONAL+=("$1") # save it in an array for later
shift # past argument
;;
esac
done
set -- "${POSITIONAL[@]}" # restore positional parameters
echo FILE EXTENSION = "${EXTENSION}"
echo SEARCH PATH = "${SEARCHPATH}"
echo LIBRARY PATH = "${LIBPATH}"
echo DEFAULT = "${DEFAULT}"
echo "Number files in SEARCH PATH with EXTENSION:" $(ls -1 "${SEARCHPATH}"/*."${EXTENSION}" | wc -l)
if [[ -n $1 ]]; then
echo "Last line of file specified as non-opt/last argument:"
tail -1 "$1"
fi
Разделение по Bash (например, --option=argument
) (без getopt [s])
Использование ./myscript.sh -e=conf -s=/etc -l=/usr/lib /etc/hosts
#!/bin/bash
for i in "$@"
do
case $i in
-e=*|--extension=*)
EXTENSION="${i#*=}"
shift # past argument=value
;;
-s=*|--searchpath=*)
SEARCHPATH="${i#*=}"
shift # past argument=value
;;
-l=*|--lib=*)
LIBPATH="${i#*=}"
shift # past argument=value
;;
--default)
DEFAULT=YES
shift # past argument with no value
;;
*)
# unknown option
;;
esac
done
echo "FILE EXTENSION = ${EXTENSION}"
echo "SEARCH PATH = ${SEARCHPATH}"
echo "LIBRARY PATH = ${LIBPATH}"
echo "Number files in SEARCH PATH with EXTENSION:" $(ls -1 "${SEARCHPATH}"/*."${EXTENSION}" | wc -l)
if [[ -n $1 ]]; then
echo "Last line of file specified as non-opt/last argument:"
tail -1 $1
fi
Чтобы лучше понять ${i#*=}
, найдите «Удаление подстроки» в этого руководства . Функционально он эквивалентен `sed 's/[^=]*=//' <<< "$i"`
, который вызывает ненужный подпроцесс, или `echo "$i" | sed 's/[^=]*=//'`
, который вызывает два ненужных подпроцесса.
Метод № 2: Использование bash с getopt [s]
от: http://mywiki.wooledge.org/BashFAQ/035#getopts
getopt (1) ограничения (более старые, относительно недавние getopt
версии):
- не может обрабатывать аргументы, которые являются пустыми строками
- не может обрабатывать аргументы со встроенным пробелом
Более поздние версии getopt
не имеют этих ограничений.
Кроме того, оболочка POSIX (и другие) предлагает getopts
, который не имеет этих ограничений. Вот упрощенный пример getopts
:
#!/bin/sh
# A POSIX variable
OPTIND=1 # Reset in case getopts has been used previously in the shell.
# Initialize our own variables:
output_file=""
verbose=0
while getopts "h?vf:" opt; do
case "$opt" in
h|\?)
show_help
exit 0
;;
v) verbose=1
;;
f) output_file=$OPTARG
;;
esac
done
shift $((OPTIND-1))
[ "${1:-}" = "--" ] && shift
echo "verbose=$verbose, output_file='$output_file', Leftovers: $@"
# End of file
Преимущества getopts
:
- Он более переносим и будет работать в других оболочках, как
dash
.
- Он может обрабатывать несколько отдельных опций, таких как
-vf filename
, обычным способом Unix, автоматически.
Недостатком getopts
является то, что он может обрабатывать только короткие опции (-h
, а не --help
) без дополнительного кода.
Существует учебник по getopts , который объясняет, что означает весь синтаксис и переменные. В bash также есть help getopts
, что может быть информативно.