Ich schreibe ein Skript, das eine Datei auswählen und bestimmte Inhalte drucken kann. Zum Beispiel:
san#./script.sh
Expected Usage : ./script.sh --file1 --dns
(Hier prüft es die Datei1, sucht nach dem DNS-Namen und druckt. Grundsätzlich gibt es unter einem Parameter Unterparameter.)
Ich habe es für einen einzelnen Parameter/eine einzelne Option wie folgt versucht:
options=$@
arguments=($options)
index=0;
for argument in $options
do
index=`expr $index + 1`;
case $argument in
-a | --fun1 ) run_function1 ;;
-b | --fun2 ) run_function2 ;;
-c | --fun3 ) run_function3 ;;
esac
done
exit;
[ ${1} ] || helpinfo
Kann jemand einen Vorschlag für einen doppelten Parameter (Unteroptionen) machen?
Erwartete Zieloptionen:
./script.sh
OPTIONS : ./script.sh -h
./script --fun1 stackoverflow
microsoft
Google
--fun2 Yahoo
Grundsätzlich schaut jede Funktion in eine Datei. Ich habe mir getopt oder getopts angesehen, aber es hat keine Long-Option (--long ist nicht möglich, stattdessen können wir nur -l verwenden). Aber ich bin mir bei den Unterparametern wieder nicht sicher. Kann mir jemand dabei helfen? Ich möchte getopt
oder nicht verwenden getopts
.
Antwort1
Diese Version ist bequemer zu verwenden als die erste, die ich hier angegeben habe. Insbesondere vermeidet sie doppelten Code für äquivalente lange und kurze Optionen. Sie sollte alles verarbeiten, was Sie jemals für Optionen benötigen: kurze Optionen ( -q
), lange Optionen ( --quiet
), Optionen mit Argumenten, akkumulierte kurze Optionen ( -qlfinput
statt -q -l -f input
), eindeutig abgekürzte lange Optionen ( --qui
statt --quiet
), Ende der Optionen durch --
.
Der größte Teil des Codes ist festgelegt; Sie müssen nur die markierten Teile ändern.
#!/bin/bash
# Update USAGE (USAGE1, USAGE2, USAGE3 may remain unchanged):
USAGE='Usage: prog [-q|--quiet] [-l|--list] [-f file|--file file] [-Q arg|--query arg] args'
USAGE1='
Ambiguously abbreviated long option:'
USAGE2='
No such option:'
USAGE3='
Missing argument for'
# List all long options here (including leading --):
LONGOPTS=(--quiet --list --file --query)
# List all short options that take an option argument here
# (without separator, without leading -):
SHORTARGOPTS=fQ
while [[ $# -ne 0 ]] ; do
# This part remains unchanged
case $1 in
--) shift ; break ;; ### no more options
-) break ;; ### no more options
-*) ARG=$1 ; shift ;;
*) break ;; ### no more options
esac
# This part remains unchanged
case $ARG in
--*)
FOUND=0
for I in "${LONGOPTS[@]}" ; do
case $I in
"$ARG") FOUND=1 ; OPT=$I ; break ;;
"$ARG"*) (( FOUND++ )) ; OPT=$I ;;
esac
done
case $FOUND in
0) echo "$USAGE$USAGE2 $ARG" 1>&2 ; exit 1 ;;
1) ;;
*) echo "$USAGE$USAGE1 $ARG" 1>&2 ; exit 1 ;;
esac ;;
-["$SHORTARGOPTS"]?*)
OPT=${ARG:0:2}
set dummy "${ARG:2}" "$@"
shift ;;
-?-*)
echo "$USAGE" 1>&2 ; exit 1 ;;
-??*)
OPT=${ARG:0:2}
set dummy -"${ARG:2}" "$@"
shift ;;
-?)
OPT=$ARG ;;
*)
echo "OOPS, this can't happen" 1>&2 ; exit 1 ;;
esac
# Give both short and long form here.
# Note: If the option takes an option argument, it it found in $1.
# Copy the argument somewhere and shift afterwards!
case $OPT in
-q|--quiet) QUIETMODE=yes ;;
-l|--list) LISTMODE=yes ;;
-f|--file) [[ $# -eq 0 ]] && { echo "$USAGE$USAGE3 $OPT" 1>&2 ; exit 1 ; }
FILE=$1 ; shift ;;
-Q|--query) [[ $# -eq 0 ]] && { echo "$USAGE$USAGE3 $OPT" 1>&2 ; exit 1 ; }
QUERYARG=$1 ; shift ;;
*) echo "$USAGE$USAGE2 $OPT" 1>&2 ; exit 1 ;;
esac
done
# Remaining arguments are now in "$@":
echo "QUIETMODE = $QUIETMODE"
echo "LISTMODE = $LISTMODE"
echo "FILE = $FILE"
echo "QUERYARG = $QUERYARG"
echo "REMAINING ARGUMENTS:" "$@"
Antwort2
Zitat. Immer zitieren. Im Zweifelsfall zitieren. Wenn kein Zweifel besteht.Zitat.
Beispiel: Ihr Test am $1
,(was nie erreicht wird, weil exit
), würde Ihr Skript zum Absturz bringen, wenn es zB mit aufgerufen wird ./myscript "file name with spaces"
.
Wenn es um Argumentschleifen geht, könnten Sie vielleicht mit etwas wie Folgendem beginnen:
#!/bin/bash
prnt_help()
{
printf "Usage: %s [OPTION]\n" $(basename "$1")
}
# A simple function only to visualize what gets passed and one of many
# ways to deal with it.
do_list()
{
printf "do_list:\n"
printf "OPT: %s\n" "$@"
printf "My list:\n"
while [[ -n "$1" && "${1:0:1}" != "-" ]]; do
printf "Processing %s\n" "$1"
shift
done
}
main()
{
while [[ -n "$1" ]];do
# This test is not needed, but include it if you find use for it.
if [[ "${1:0:1}" != "-" ]]; then
shift
continue
fi
# Check option and pass rest of arguments to matching function
printf "Checking option %s\n" "$1"
case "$1" in
"-l"|"--list") shift; do_list "$@";;
"-h"|"--help") prnt_help "$0";;
"--") printf "Rest is not options even if starts with -\n"
break;;
esac
shift
done
# If you use "--" to separate out e.g. filenames starting with -
# then process them here.
}
main "$@"
Antwort3
Eingebautgetopts
Analysieren Sie nur kurze Optionen (außer ksh93), aber Sie können trotzdem einige Skriptzeilen hinzufügen, damit getopts lange Optionen verarbeitet.
Hier ist ein Teil des Codes inhttp://www.uxora.com/unix/shell-script/22-handle-long-options-with-getopts
#== set short options ==#
SCRIPT_OPTS=':fbF:B:-:h'
#== set long options associated with short one ==#
typeset -A ARRAY_OPTS
ARRAY_OPTS=(
[foo]=f
[bar]=b
[foobar]=F
[barfoo]=B
[help]=h
[man]=h
)
#== parse options ==#
while getopts ${SCRIPT_OPTS} OPTION ; do
#== translate long options to short ==#
if [[ "x$OPTION" == "x-" ]]; then
LONG_OPTION=$OPTARG
LONG_OPTARG=$(echo $LONG_OPTION | grep "=" | cut -d'=' -f2)
LONG_OPTIND=-1
[[ "x$LONG_OPTARG" = "x" ]] && LONG_OPTIND=$OPTIND || LONG_OPTION=$(echo $OPTARG | cut -d'=' -f1)
[[ $LONG_OPTIND -ne -1 ]] && eval LONG_OPTARG="\$$LONG_OPTIND"
OPTION=${ARRAY_OPTS[$LONG_OPTION]}
[[ "x$OPTION" = "x" ]] && OPTION="?" OPTARG="-$LONG_OPTION"
if [[ $( echo "${SCRIPT_OPTS}" | grep -c "${OPTION}:" ) -eq 1 ]]; then
if [[ "x${LONG_OPTARG}" = "x" ]] || [[ "${LONG_OPTARG}" = -* ]]; then
OPTION=":" OPTARG="-$LONG_OPTION"
else
OPTARG="$LONG_OPTARG";
if [[ $LONG_OPTIND -ne -1 ]]; then
[[ $OPTIND -le $Optnum ]] && OPTIND=$(( $OPTIND+1 ))
shift $OPTIND
OPTIND=1
fi
fi
fi
fi
#== discard option argument start with hyphen ==#
if [[ "x${OPTION}" != "x:" ]] && [[ "x${OPTION}" != "x?" ]] && [[ "${OPTARG}" = -* ]]; then
OPTARG="$OPTION" OPTION=":"
fi
#== manage options ==#
case "$OPTION" in
f ) foo=1 bar=0 ;;
b ) foo=0 bar=1 ;;
B ) barfoo=${OPTARG} ;;
F ) foobar=1 && foobar_name=${OPTARG} ;;
h ) usagefull && exit 0 ;;
: ) echo "${SCRIPT_NAME}: -$OPTARG: option requires an argument" >&2 && usage >&2 && exit 99 ;;
? ) echo "${SCRIPT_NAME}: -$OPTARG: unknown option" >&2 && usage >&2 && exit 99 ;;
esac
done
shift $((${OPTIND} - 1))
Hier ist ein Test:
# Short options test
$ ./foobar_any_getopts.sh -bF "Hello world" -B 6 file1 file2
foo=0 bar=1
barfoo=6
foobar=1 foobar_name=Hello world
files=file1 file2
# Long and short options test
$ ./foobar_any_getopts.sh --bar -F Hello --barfoo 6 file1 file2
foo=0 bar=1
barfoo=6
foobar=1 foobar_name=Hello
files=file1 file2
Ansonstenin den letzten Korn Shellksh93 getopts
kann natürlich lange Optionen analysieren und sogar eine Manpage anzeigen. (siehehttp://www.uxora.com/unix/shell-script/20-getopts-with-man-page-and-long-options).