Английская Википедия:Getopts
Шаблон:Short description
Шаблон:Confuse
Шаблон:Refimprove
Шаблон:Lowercase
Шаблон:Infobox software
getopts
is a built-in Unix shell command for parsing command-line arguments. It is designed to process command line arguments that follow the POSIX Utility Syntax Guidelines, based on the C interface of getopt.
The predecessor to Шаблон:Code was the external program Шаблон:Code by Unix System Laboratories.
History
The original Шаблон:Code had several problems: it could not handle whitespace or shell metacharacters in arguments, and there was no ability to disable the output of error messages.[1]
getopts
was first introduced in 1986 in the Bourne shell shipped with Unix SVR3. It uses the shell's own variables to track the position of current and argument positions, Шаблон:Tt and Шаблон:Tt, and returns the option name in a shell variable.[2] Earlier versions of the Bourne shell did not have getopts.
In 1995, getopts
was included in the Single UNIX Specification version 1 / X/Open Portability Guidelines Issue 4.[3] As a result, getopts
is now available in shells including the Bourne shell, KornShell, Almquist shell, Bash and Zsh.[4]
The Шаблон:Mono command has also been ported to the IBM i operating system.[5]
The modern usage of Шаблон:Code was partially revived mainly due to an enhanced implementation in util-linux. This version, based on the BSD Шаблон:Code, not only fixed the two complaints around the old Шаблон:Code, but also introduced the capability for parsing GNU-style long options and optional arguments for options, features that Шаблон:Code lacks.[6] The various BSD distributions, however, stuck to the old implementation.[1]
Usage
The usage synopsis of getopt and getopts is similar to its C sibling:
getopt optstring [parameters] getopts optstring varname [parameters]
- The optstring part has the same format as the C sibling.
- The parameters part simply accepts whatever one wants getopt to parse. A common value is all the parameters, Шаблон:Tt in POSIX shell.
- This value exists in getopts but is rarely used, since it can just access the shell's parameters. It is useful with resetting the parser, however.
- The varname part of getopts names a shell variable to store the option parsed into.
The way one uses the commands however varies a lot:
- getopt simply returns a flat string containing whitespace-separated tokens representing the "normalized" argument. One then uses a while-loop to parse it natively.[1]
- getopts is meant to be repeatedly called like the C getopt. When it hits the end of arguments, it returns 1 (shell false).[3]
Enhancements
In various getopts
In spring 2004 (Solaris 10 beta development), the libc implementation for Шаблон:Tt was enhanced to support long options. As a result, this new feature was also available in the built-in command getopts
of the Bourne Shell. This is triggered by parenthesized suffixes in the optstring specifying long aliases.[7]
KornShell and Zsh both have an extension for long arguments. The former is defined as in Solaris,[8] while the latter is implemented via a separate Шаблон:Code command.[9]
KornShell additionally implements optstring extensions for options beginning with Шаблон:Code instead of Шаблон:Code.[8]
In Linux getopt
An alternative to getopts
is the Linux enhanced version of getopt
, the external command line program.
The Linux enhanced version of getopt
has the extra safety of getopts
plus more advanced features. It supports long option names (e.g. --help
) and the options do not have to appear before all the operands (e.g. command operand1 operand2 -a operand3 -b
is permitted by the Linux enhanced version of getopt
but does not work with getopts
). It also supports escaping metacharacters for shells (like tcsh and POSIX sh) and optional arguments.[6]
Comparison
Шаблон:Diagonal split header | POSIX getopts | Solaris/ksh getopts | Unix/BSD getopt | Linux getopt |
---|---|---|---|---|
Splits options for easy parsing | Шаблон:Yes | Шаблон:Yes | Шаблон:Yes | Шаблон:Yes |
Allows suppressing error messages | Шаблон:Yes | Шаблон:Yes | Шаблон:No | Шаблон:Yes |
Safe with whitespace and metacharacters | Шаблон:Yes | Шаблон:Yes | Шаблон:No | Шаблон:Yes |
Allows operands to be mixed with options | Шаблон:No | Шаблон:Yes | Шаблон:No | Шаблон:Yes |
Supports long options | Шаблон:Maybe | Шаблон:Yes | Шаблон:No | Шаблон:Yes |
Optional arguments | Шаблон:Maybe | Шаблон:Maybe | Шаблон:No | Шаблон:Yes |
Examples
Suppose we are building a Wikipedia downloader in bash that takes three options and zero extra arguments:
wpdown -a article name -l [language] -v
When possible, we allow the following long arguments:
-a --article -l --language, --lang -v --verbose
For clarity, no help text is included, and we assume there is a program that downloads any webpage. In addition, all programs are of the form:
#!/bin/bash
VERBOSE=0
ARTICLE=''
LANG=en
# [EXAMPLE HERE]
if ((VERBOSE > 2)); then
printf '%s\n' 'Non-option arguments:'
printf '%q ' "${remaining[@]]}"
fi
if ((VERBOSE > 1)); then
printf 'Downloading %s:%s\n' "$LANG" "$ARTICLE"
fi
if [[ ! $ARTICLE ]]; then
printf '%s\n' "No articles!">&2
exit 1
fi
save_webpage "https://${LANG}.wikipedia.org/wiki/${ARTICLE}"
Using old getopt
The old getopt does not support optional arguments:
# parse everything; if it fails we bail
args=`getopt 'a:l:v' $*` || exit
# now we have the sanitized args... replace the original with it
set -- $args
while true; do
case $1 in
(-v) ((VERBOSE++)); shift;;
(-a) ARTICLE=$2; shift 2;;
(-l) LANG=$2; shift 2;;
(--) shift; break;;
(*) exit 1;; # error
esac
done
remaining=("$@")
This script will also break with any article title with a space or a shell metacharacter (like ? or *) in it.
Using getopts
Getopts give the script the look and feel of the C interface, although in POSIX optional arguments are still absent:
#!/bin/sh
while getopts ':a:l:v' opt; do
case $opt in
(v) ((VERBOSE++));;
(a) ARTICLE=$OPTARG;;
(l) LANG=$OPTARG;;
(:) # "optional arguments" (missing option-argument handling)
case $OPTARG in
(a) exit 1;; # error, according to our syntax
(l) :;; # acceptable but does nothing
esac;;
esac
done
shift "$OPTIND"
# remaining is "$@"
Since we are no longer operating on shell options directly, we no longer need to shift them. However, a slicing operating is required to get the remaining arguments now.
It is possible but tedious to emulate long option support by treating Шаблон:Code as an argument Шаблон:Code to an option Шаблон:Code. Long options with an argument is only possible when it is delineated by Шаблон:Tt.[10]
Using Linux getopt
Linux getopt escapes its output and an "eval" command is needed to have the shell interpret it. The rest is unchanged:
#!/bin/bash
# We use "${@}" instead of "${*}" to preserve argument-boundary information
ARGS=$(getopt --options 'a:l::v' --longoptions 'article:,lang::,language::,verbose' -- "${@}") || exit
eval "set -- ${ARGS}"
while true; do
case "${1}" in
(-v | --verbose)
((VERBOSE++))
shift
;;
(-a | --article)
ARTICLE="${2}"
shift 2
;;
(-l | --lang | --language)
# handle optional: getopt normalizes it into an empty string
if [ -n "${2}" ] ; then
LANG="${2}"
fi
shift 2
;;
(--)
shift
break
;;
(*)
exit 1 # error
;;
esac
done
remaining_args=("${@}")
See also
References
External links