Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Parameter des Scriptes

6 views
Skip to first unread message

Philipp Kraus

unread,
Apr 27, 2012, 5:41:31 AM4/27/12
to
Hallo,

ich benutze zurzeit bei einem Script die getopts Funktion, um die
Parameter zu setzen:

while getopts "k:s:f" opt; do
case $opt in

Da aber nun doch recht viele weitere Parameter hinzu kommen würde ich
gerne z.B.
das ganze einmal als
myscript -k schlüssel
oder
myscript --key schlüssel

als Eingabe ermöglichen. Bei getopts kann man ja nur einzelne
Buchstaben verwenden.
Mein Script hat nur einen festen Parameter, d.h. der letzte Parameter
hat keinen Schlüssel, d.h.
der Aufruf sieht so aus myscript <key, value>* filename
ich kann also beliebig viele Schlüssel-Value-Paare vor dem filename
haben, wobei für den Schüssel
entweder eine Kurzform - <alpha>* möglich sein soll oder eben eine
Langform -- <Wort>

Wie verarbeitet man eine solche Parameterliste am besten in einem Bashscript?

Danke

Phil

Paul Hink

unread,
Apr 27, 2012, 8:33:58 AM4/27/12
to
Philipp Kraus <philip...@flashpixx.de> wrote:

> Mein Script hat nur einen festen Parameter, d.h. der letzte Parameter
> hat keinen Schlüssel, d.h.
> der Aufruf sieht so aus myscript <key, value>* filename
> ich kann also beliebig viele Schlüssel-Value-Paare vor dem filename
> haben, wobei für den Schüssel
> entweder eine Kurzform - <alpha>* möglich sein soll oder eben eine
> Langform -- <Wort>
>
> Wie verarbeitet man eine solche Parameterliste am besten in einem Bashscript?

Ein möglicher Ansatz (Skizze, ungetestet):

while [ "$#" -ge 3 ]; do
case "$1" in
-k|--key) echo "key = $2";;
-f|--foo) echo "foo = $2";;
...
*) echo "Invalid argument '$1'."; break;;
esac
shift 2
done

if [ "$#" -ne 1 ]; then
echo "Usage error."
exit
fi

filename="$1"

Martin Vaeth

unread,
Apr 27, 2012, 11:02:24 AM4/27/12
to
Philipp Kraus <philip...@flashpixx.de> schrieb:
> myscript -k schlüssel
> oder
> myscript --key schlüssel

Statt getopt muss man dann halt "von Hand" parsen.
Ein Beispiel, in dem das geschieht (um unbekannte
Parameter weiterzureichen) ist hier:
https://github.com/vaeth/diffhelp/blob/master/diffhelp
In dem Beispiel wird zwar nur die Kurzform behandelt,
aber die Erweiterung für die Langform ist trivial.

Philipp Kraus

unread,
Apr 27, 2012, 5:17:09 PM4/27/12
to
da ich ja immer bis auf das letzte Argument Key-Value-Tupel hab, kann
ich doch auch bei Bash 4 das ganze als assoziatives Array verwenden,
wenn ich das richtig sehe, oder?


Thomas 'PointedEars' Lahn

unread,
Apr 28, 2012, 3:59:41 AM4/28/12
to
Philipp Kraus wrote:

> ich benutze zurzeit bei einem Script die getopts Funktion, um die
> Parameter zu setzen:
>
> while getopts "k:s:f" opt; do
> case $opt in
>
> Da aber nun doch recht viele weitere Parameter hinzu kommen würde ich
> gerne z.B.
> das ganze einmal als
> myscript -k schlüssel
> oder
> myscript --key schlüssel
>
> als Eingabe ermöglichen. Bei getopts kann man ja nur einzelne
> Buchstaben verwenden.
> […]
> Wie verarbeitet man eine solche Parameterliste am besten in einem
> Bashscript?

In einem Script für die (*GNU*) bash(1) macht man das am besten mit
*GNU* getopt(1), welches *GNU* getopt(3) verwendet.

--
PointedEars

Please do not Cc: me. / Bitte keine Kopien per E-Mail.

Uwe Borchert

unread,
Apr 28, 2012, 7:03:42 AM4/28/12
to
Hallo,

Am 27.04.2012 11:41, schrieb Philipp Kraus:

> Da aber nun doch recht viele weitere Parameter hinzu kommen ...

> Wie verarbeitet man eine solche Parameterliste am besten in einem
> Bashscript?

Eine Möglichkeit ist in einer Schleife mit case auf $1 unterscheiden und
dann shiften, wenn $1 leer ausbrechen ... Ausschnitt:

while true
do
case "$1" in
-6) MONTAGE="6X";;
-8) MONTAGE="8X";;
-gamma) shift
OPTIONS="$OPTIONS -gamma $1" ;;
-?) echo "Benutzung von $0"
echo "$0 [OPTIONS] Eingabedatei [Ausgabedatei]"
echo "Optionen:"
echo " [-6|-8] Anzahl der Kacheln 6 oder 8 (ist Vorgabe)"
echo " [-gamma FLOAT] Gamma-Korrektur"
;;
-*) OPTIONS="$OPTIONS $1" ;;
*) break ;;
esac
shift
done

Der komplette Bleistift mit Parameterweitwurf:................


#/bin/bash
#
# pass2foto.sh
#
# created 04.07.2008, ubs
# last update 05.07.2008, ubs
#
echo
echo "*******************************************"
echo "* Passbild für Foto-Kiosk vorbereiten ... *"
echo "*******************************************"
echo

# ---------------------------------------
# Bildqualität:
#
OPTIONS="-quality 100"
#
# ---------------------------------------
# Weitere Optionen:

MONTAGE="8X" # Vorgabe 4 x 2 = 8 Bilder

while true
do
case "$1" in
-6) MONTAGE="6X";;
-8) MONTAGE="8X";;
-gamma) shift
OPTIONS="$OPTIONS -gamma $1" ;;
-?) echo "Benutzung von $0"
echo "$0 [OPTIONS] Eingabedatei [Ausgabedatei]"
echo "Optionen:"
echo " [-6|-8] Anzahl der Kacheln 6 oder 8 (ist Vorgabe)"
echo " [-gamma FLOAT] Gamma-Korrektur"
;;
-*) OPTIONS="$OPTIONS $1" ;;
*) break ;;
esac
shift
done
# echo "Montage: $MONTAGE"
echo "Kacheln ($MONTAGE) von Passfotos auf ein 10 x 15 cm Bild mit 600 dpi"

if [ $# -eq 0 ]
then
echo "Mindestens die Eingabedatei muß angegeben werden!"
echo " "
echo "$0 [OPTIONS] Eingabedatei [Ausgabedatei]"
echo "Optionen:"
echo " [-6|-8] Anzahl der Kacheln 6 oder 8 (ist Vorgabe)"
echo " [-gamma FLOAT] Gamma-Korrektur"
exit
fi

infile="$1"

if [ $# -eq 2 ]
then
outfile="$2"
echo "Name der Ausgabedatei wurde übergeben ($outfile)."
else
outfile="10x15cm.jpg"
echo "Name der Ausgabedatei wurde nicht angegeben."
fi

echo
echo "Eingabedatei -> $infile"
echo "Ausgabedatei -> $outfile"
echo
# ---------------------------------------
# Abmessungen in Pixel:.
#
# Passbild (Hochformat)
# Metrisch 35 x 45 mm
# Points (1/72 Inch) 99 x 128 pts
# Pixel (600 dpi) 827 x 1063 px
#
# Foto (Querformat)
# Originalformat 4 x 6 Zoll
# Metrisch 15 x 10 cm
# Points 432 x 288 pts
# Pixel (600 dpi) 3600 x 2400 px
#
# Resultierende Abstaende:
# Gap in Pixel 36,5 + 68,5 px
#
# Ideales Fototerminal
#
# echo $MONTAGE
#
if [ "$MONTAGE" = "8X" ]
then
GEOMETRY="-geometry 827x1063+36+68"
INFILES="$1 $1 $1 $1 $1 $1 $1 $1"
OPTIONS="$OPTIONS -tile 4x2"
elif [ "$MONTAGE" = "6X" ]
then
GEOMETRY="-geometry 827x1063+185+68"
INFILES="$1 $1 $1 $1 $1 $1"
OPTIONS="$OPTIONS -tile 3x2"
fi
#
# ---------------------------------------
# Das Foto wird jeweils 2 px kleiner!
# ---------------------------------------
#
# Kodak_Fototerminal:............................
# Darstellung 2,5% zu gross, Bild 10,2 x 15,2 cm
#................................................
# Alle Angaben in Pixel (600 dpi)
# Passbild 807 x 1037
# Fotopapier 3591 x 2409
# Gap 91 x 168
# Rand (2mm) 47
# ---------------------------------------
#
# GEOMETRY="-geometry 807x1037+45+84"
OPTIONS="$OPTIONS -profile /usr/local/share/color/icc/eciRGB_v2.icc"
#
#
#
echo "GEOMETRY : $GEOMETRY"
echo "OPTIONS : $OPTIONS"
#
# ImageMagick montage:.
#
montage \
$GEOMETRY $OPTIONS $INFILES \
$outfile

echo "Fertig! Ergebnis wurde in $outfile geschrieben."
echo
echo "*******************************************"
echo "* Passbild ist für Foto-Kiosk vorbereitet *"
echo "*******************************************"
echo

...[Radiergummi, Ende Bleistift]...

MfG

Uwe Borchert

Thomas 'PointedEars' Lahn

unread,
Apr 28, 2012, 9:30:35 AM4/28/12
to
Uwe Borchert wrote:

> Am 27.04.2012 11:41, schrieb Philipp Kraus:
>> Da aber nun doch recht viele weitere Parameter hinzu kommen ...
>>
>> Wie verarbeitet man eine solche Parameterliste am besten in einem
>> Bashscript?
>
> Eine Möglichkeit ist in einer Schleife mit case auf $1 unterscheiden und
> dann shiften, wenn $1 leer ausbrechen ...

Das funktioniert nur dann, wenn alle Optionen vor den positionalen
Parametern angegeben werden. POSIX empfiehlt jedoch u. a., dass die
Reihenfolge von Optionen egal ist und dass nach `--' kein Parameter mehr
eine Option ist:

<http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html>

`getopts' beachtet all dies; Dein Ansatz nicht.

getopt(1) – welches diese Probleme Deines Ansatzes nicht hat – existiert.
Ein getopt(1), welches die langen (GNU-)Optionen unterstützt, wird zusammen
mit (GNU) bash(1) ausgeliefert. Rad 1.0 funktioniert also; man muss es
nicht in Rad 1.1 verschlimmbessern.

Konkret hat sich hier folgender Ansatz bewährt (wahrscheinlich mithilfe
irgendeines bash-Tutorial zusammengebastelt, ich erinnere mich nicht mehr):

if `getopt -T >/dev/null 2>&1`; [ $? = 4 ]; then
getopt_type=long
tmp=`getopt -o vhVf::p: \
-l verbose,help,version,file::,port: \
-n "$appname" \
-- "$@"`
else
getopt_type=short
tmp=`getopt vhVf:p: "$@"`
fi

getopt_exit_code=$?
help=0
unset verbose
show_version=0
file=''
port=$FOO_PORT
args=""

if [ $getopt_exit_code -eq 0 ]; then
eval set -- "$tmp"
while true
do
case "$1" in
-h | --help) help=1; shift;;
-v | --verbose) verbose='-v'; shift;;
-V | --version) show_version=1; shift;;
-f | --file) shift; file="${1:--}"; shift;;
-p | --port) shift; port=$1; shift;;
--) shift; break;;
esac
done
[ -n "$*" ] && args=$args" $*"
[ -z "$args" -a $show_version -eq 0 -a -z "$file" ] && help=1
set -- $args
else
if [ $getopt_exit_code -eq 1 ] || [ $getopt_exit_code -eq 2 ]; then
echo
help=1
else
exit $getopt_exit_code
fi
fi

usw.

Uwe Borchert

unread,
Apr 28, 2012, 9:45:32 AM4/28/12
to
Hallo,

Am 28.04.2012 15:30, schrieb Thomas 'PointedEars' Lahn:
> Uwe Borchert wrote:
>
>> Am 27.04.2012 11:41, schrieb Philipp Kraus:
>>> Da aber nun doch recht viele weitere Parameter hinzu kommen ...
>>>
>>> Wie verarbeitet man eine solche Parameterliste am besten in einem
>>> Bashscript?
>>
>> Eine Möglichkeit ist in einer Schleife mit case auf $1 unterscheiden und
>> dann shiften, wenn $1 leer ausbrechen ...
>
> Das funktioniert nur dann, wenn alle Optionen vor den positionalen
> Parametern angegeben werden. POSIX empfiehlt jedoch u. a., dass die
> Reihenfolge von Optionen egal ist und dass nach `--' kein Parameter mehr
> eine Option ist:
>
> <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html>
>
> `getopts' beachtet all dies; Dein Ansatz nicht.

Ja. Es war sogar ausdrücklich nicht erwünscht. Ich wollte/musste konsistent
zur typischen Nutzung anderer Konversionsprogramme bleiben. Daher passt mein
Beispiel in diesem Fall vielleicht nicht so ganz.

...[Danke noch für das Beispiel für den anderen Ansatz]...

MfG

Uwe Borchert

Philipp Kraus

unread,
Apr 28, 2012, 4:43:23 PM4/28/12
to
On 2012-04-28 15:30:35 +0200, Thomas 'PointedEars' Lahn said:

> Uwe Borchert wrote:
>
>> Am 27.04.2012 11:41, schrieb Philipp Kraus:
>>> Da aber nun doch recht viele weitere Parameter hinzu kommen ...
>>>
>>> Wie verarbeitet man eine solche Parameterliste am besten in einem
>>> Bashscript?
>>
>> Eine Möglichkeit ist in einer Schleife mit case auf $1 unterscheiden und
>> dann shiften, wenn $1 leer ausbrechen ...
>
> Das funktioniert nur dann, wenn alle Optionen vor den positionalen
> Parametern angegeben werden. POSIX empfiehlt jedoch u. a., dass die
> Reihenfolge von Optionen egal ist und dass nach `--' kein Parameter mehr
> eine Option ist:
>
> <http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap12.html>
>
> `getopts' beachtet all dies; Dein Ansatz nicht.
>
> getopt(1) – welches diese Probleme Deines Ansatzes nicht hat – existiert.
> Ein getopt(1), welches die langen (GNU-)Optionen unterstützt, wird zusammen
> mit (GNU) bash(1) ausgeliefert. Rad 1.0 funktioniert also; man muss es
> nicht in Rad 1.1 verschlimmbessern.
>
> Konkret hat sich hier folgender Ansatz bewährt (wahrscheinlich mithilfe
> irgendeines bash-Tutorial zusammengebastelt, ich erinnere mich nicht mehr):

Danke, ich muss mich nun durch den Beispielcode einmal durcharbeiten, weil
ich ihn so auf Anhieb noch nicht verstehe

Vielen Dank

0 new messages