shell: Vergleich eines Wertes mit dem einer Liste

Post Reply
Message
Author
rossi

shell: Vergleich eines Wertes mit dem einer Liste

#1 Post by rossi »

Hallo,

ich würde gerne überprüfen, ob ein Wert identisch mit einem anderen einer Liste ist.
Hab erfloglos folgendes versucht:

-----
#!/bin/sh

ARG="eine kuh macht muh"

if ${1} in ${ARG}; then
echo 'Alles im Lot'
else
echo 'Alternativen bitte !'
fi

------

Ich würde hier gerne testen, ob das erste dem Skript übergebene Argument ($1) mit einem der Worte in $ARG übereinstimmt. Wenn also $1 entweder "eine" oder "kuh" oder "macht" oder "muh" ist, soll der Text "alles im Lot" ausgegeben werden. Anderenfalls halt die Bitte nach den Alternativen. Sorry für die Auschweifung, aber ich wußte mangels Fachjargon nicht, das besser zu beschreiben.

Nun täte ungerne hierfür eine "case" Anweisung basteln, weil die Argumentliste variabel sein wird und erst mit Skriptaufruf erstellt wird. Und ich denke (hoffe), es geht auch eleganter als mit einer "for" Schleife.
Und wie immer, ziehe ich "sh" der "bash" vor. Einfach wegen der sauberen Grundschule.

Chris

Re: shell: Vergleich eines Wertes mit dem einer Liste

#2 Post by Chris »

Hi Rossi!

Klar geht's einfacher...

<blockquote><pre><font size="1" face="">code:</font><hr><font face="Courier New" size="2">
#!/bin/sh

ARG="eine kuh macht muh"

echo $ARG | grep -q $1
[ $? -eq 0 ] && echo 'Alles im Lot' || echo 'Alternativen bitte !'
</font><hr></pre></blockquote>


Gruß
Chris

rossi

Re: shell: Vergleich eines Wertes mit dem einer Liste

#3 Post by rossi »

Autsch. Hätte man fast noch selber drauf kommen können. Hab schon wieder wirre Befehlsinterpretationen gesucht ;) Auf jeden Fall vielen Dank.

Noch eine Frage zu der "[ args ] $$ do" Notation.

Kann ich auch bei Erfüllung zwei Befehle ausführen oder muß ich dann zu "if" greifen, quasi:

[ a != b ] && echo "Falsch"; exit 1 || echo "Richtig"

Haut so nicht hin, klar, aber kann ich der sh zwei Befehle als einen vorkaukeln ? "if" sieht so häßlich aus bei nur zwei Zeilen ... und macht dat Ding unnötig (?) größer und vor allem unübersichtlicher.

Jochen

Re: shell: Vergleich eines Wertes mit dem einer Liste

#4 Post by Jochen »

@Chris:

Lange und teils schmerzhafte Erfahrung mit Regulären Ausdrücken hat mich gelehrt, diese sehr vorsichtig zu formulieren; daher hätte ich noch einen Verbesserungsvorschlag zu Deiner grep-Zeile.<pre>echo "$ARG" | grep '\<!--no--><'"$1"'\<!--no-->>' >/dev/null 2>&1</pre>So geht die Shell einmal nicht an den Inhalt der Variablen dran und ändert ihn eigenmächtig, und grep sucht nach ganzen Wörtern in der Argumentliste, denn sonst würde beispielsweise ein "u" als Argument auch passen. Die Option "-q" zu grep ist praktisch, nach meiner Erfahrung aber leider nicht sehr portabel; daher verwende ich lieber die "althergebrachte" Methode der Umlenkung nach /dev/null.

Nächster Punkt: Explizit "$?" mit test zu verwenden ist meist doppelt gemoppelt: Wenn man schon eine Exit-Code hat, kann man auch direkt auf ihn reagieren und nicht erst den Exit-Code verwenden, um genau den gleichen durch test reproduzieren zu lassen. Die Schreibweise wäre dann <blockquote><pre><font size="1" face="">code:</font><hr><font face="Courier New" size="2">
echo "$ARG" | grep '\<!--no--><'"$1"'\>' >/dev/null 2>&1 && echo "Alles im Lot" || echo "Alternativen bitte"
</font><hr></pre></blockquote>

@rossi:
Über das Aussehen des "if"s lässt sich streiten, ich persönlich mag die ausführliche Variante lieber. Vor allem, wenn man tatsächlich mehrere Kommandos in so einem Konstrukt gruppiert:<pre>echo "$ARG" | grep '\<!--no--><'"$1"'\>' >/dev/null 2>&1 && { echo "Alles im Lot"; exit 0 ; } || { echo "Alternativen bitte"; exit 1 ; }</pre>Ganz schön unübersichtlich, ne? Zur Theorie: Kommandos kannst Du in der Shell auf zwei Arten gruppieren, und zwar mittels runder Klammern und geschweifter Klammern. Bei runden Klammern werden die Kommandos in einer Subshell ausgeführt, also ein eigener Prozess dazu verwendet. Bei geschweiften Klammern werden die Kommandos in der laufenden Shell selbst ausgeführt. Achte genau auf die Syntax:<pre>{ cmd1 ; cmd2 ; }</pre>Die Klammerung <b>muss</b> mit "; }" enden!

(Das ist alles übrigens reine Bourne-Shell und damit auch ziemlich portabel.)

Jochen

Post Reply