verwende ich folgende Zeilen (hoffe, das ist beste Praxis, wenn nicht korrigiert mich bitte) Befehlszeilenoptionen zu handhaben:Bash - getopts - Massen Argumente (Operanden) an erster Stelle in Argument Befehlszeile übergeben
#!/usr/bin/bash
read -r -d '' HELP <<EOF
OPTIONS:
-c Enable color output
-d Enable debug output
-v Enable verbose output
-n Only download files (mutually exclusive with -r)
-r Only remove files (mutually exclusive with -n)
-h Display this help
EOF
# DECLARE VARIABLES WITH DEFAULT VALUES
color=0
debug=0
verbose=0
download=0
remove=0
OPTIND=1 # Reset in case getopts has been used previously in the shell
invalid_options=(); # Array for invalid options
while getopts ":cdvnrh" opt; do
echo "Actual opt: $opt"
case $opt in
c)
color=1
;;
d)
debug=1
;;
v)
verbose=1
;;
n)
download=1
;;
r)
remove=1
;;
h)
echo "$HELP"
exit 1
;;
\?)
invalid_options+=($OPTARG)
;;
*)
invalid_options+=($OPTARG)
;;
esac
done
# HANDLE INVALID OPTIONS
if [ ${#invalid_options[@]} -ne 0 ]; then
echo "Invalid option(s):" >&2
for i in "${invalid_options[@]}"; do
echo $i >&2
done
echo "" >&2
echo "$HELP" >&2
exit 1
fi
# SET $1 TO FIRST MASS ARGUMENT, $2 TO SECOND MASS ARGUMENT ETC
shift $((OPTIND - 1))
# HANDLE CORRECT NUMBER OF MASS OPTIONS
if [ $# -ne 2 ]; then
echo "Correct number of mass arguments are 2"
echo "" >&2
echo "$HELP" >&2
exit 1
fi
# HANDLE MUTUALLY EXCLUSIVE OPTIONS
if [ $download -eq 1 ] && [ $remove -eq 1 ]; then
echo "Options for download and remove are mutually exclusive" >&2
echo "$HELP" >&2
exit 1
fi
echo "color: $color"
echo "debug: $debug"
echo "verbose: $verbose"
echo "download: $download"
echo "remove: $remove"
echo "\$1: $1"
echo "\$2: $2"
Wenn ich nenne das Skript Art und Weise, dass mass arguments (diejenigen, die nicht Schalter oder Argumente für Schalter sind) sind letzte Argumente alles korrekt funktioniert:
$ ./getopts.sh -c -d -v -r a b
Actual opt: c
Actual opt: d
Actual opt: v
Actual opt: r
color: 1
debug: 1
verbose: 1
download: 0
remove: 1
$1: a
$2: b
Das Problem ist, wenn ich das Skript aufgerufen werden soll, so dass die Masse Argumente ersten sind (oder irgendwo in der Mitte von Schaltern, die d o verwenden Argumente nicht)
$ ./getopts.sh a b -c -d -v -r
Correct number of mass arguments are 2
OPTIONS:
-c Enable color output
-d Enable debug output
-v Enable verbose output
-n Only download files (mutually exclusive with -r)
-r Only remove files (mutually exclusive with -d)
-h Display this help
oder
$ ./getopts.sh -c a b -d -v -r
Actual opt: c
Correct number of mass arguments are 2
OPTIONS:
-c Enable color output
-d Enable debug output
-v Enable verbose output
-n Only download files (mutually exclusive with -r)
-r Only remove files (mutually exclusive with -d)
-h Display this help
Ich denke, dies in Ordnung sein sollte nach (POSIX) Standards, da Syntax folgt das ist im Grunde das gleiche funktioniert wie auf meinem System erwartet:
$ cp test1/ test2/ -r
$ cp test1/ -r test2/
ich habe über das Internet suchen, aber nur, was mir in der Nähe Problem war, this one im Zusammenhang mit C.
Ihre Beobachtungen sind korrekt: getopts gibt einen Exit-Status zurück, wenn das erste Nicht-Optionsargument gefunden wird, sodass die while-Schleife endet. Ich glaube, [getopt'] (http://man.cx/getopt) kann so flexibel arbeiten, wie Sie wollen. –
@glennjackman gibt es Empfehlungen für die Verwendung von getopts über getopt. AFAIK getopt gilt als obsolet. –
Ich glaube nicht, dass getopt als veraltet gilt. getopts ist einfacher zu benutzen (IMO: es ist, was ich benutze), aber es zwingt Sie, die Optionen vor die erforderlichen Parameter zu setzen, und Sie können --longoptions nicht verwenden. –