bash: contains

Das contains – Schlüsselwort ist praktisch, um eine Liste von Parametern darauf hin zu testen, ob sie ein bestimmtes Wort enthält. Die Syntax ist so, dass, da es in der Bash keine Listen gibt, der erste Parameter das zu prüfende Wort ist, und der Rest der Parameter ist die Liste.

Was in Scala etwa

List (1, 2, 4, 9).contains (4)

wäre, wäre in der Bash:

contains 4 1 2 4 9

Nun sieht jeder natürlich gleich, dass 4 in der Liste 1, 2, 4, 9 enthalten ist. Aber die 4, die Liste oder beides könnte eine Variable sein oder die dynamische Ausgabe eines Kommandos. Eine beispielhafte Verwendung:

contains ppp0 $(ifconfig) && echo ja || echo nein

ja

Dumm nur, dass die Bash kein contains-Schlüsselwort kennt. Man kann aber eine eigene Funktion definieren – zum Beispiel so:

contains () {

 param=$1

 shift

 for elem in "$@"

 do

    [[ "$param" = "$elem" ]] && return 0

 done

return 1

}

Man könnte auch versuchen statt der fehlenden Liste, samt Funktionen, ein Array, die einzige Sammelvariable der Bash, zu verwenden. Da es für Arrays aber keine Vielzahl an Funktionen gibt, insbesondere keine contains-Funktion, drängt sich das Array nicht auf. Deren Handhabung ist in der Bash auch nicht bequem – an manchen Stellen finden sich Warnungen, dass etwas nicht mit Arrays geht – das muss man dann im Kopf behalten oder ständig nachschlagen oder ausprobieren.

Sprachlich läge es näher die Argumente andersrum zu benutzen: contains List Element, aber das erste Element ist leichter zu packen als das letzte, um dann mit Shift den Rest übrigzuhalten.

Die scheinbar naheliegende Lösung mit einem Array klappt nicht:

function contains () {
list=$1
elem=$2
echo suche $elem in  ${list[@]}
}

arr=(4 1 2 9)
contains ${arr[@]} 2

suche 1 in 4

Sie klappt nicht, da das Array nicht als erster Parameter aufgegriffen werden kann, sondern nur das erste Element. Allerdings komme ich beim experimentieren darauf, dass man mit egrep eigentlich alle Fälle prima abdecken kann –

echo ${arr[*]} | egrep -q "\b4\b" && echo ja || echo nein

echo 11 21 41 91 | egrep -q "\b4\b" && echo ja || echo nein

– das Vermeiden von Treffern in Teilstrings erfordert die Backslash-b-Konstrukte (b für boundary, Grenze (Wortgrenze)) für egrep und -q um die Ausgabe zu unterdrücken (quiet), und auch wirklich das Äquivalent der obigen contains-Funktion zu erzeugen, die einen boolschen Wert zurückgibt ohne eine Ausgabe zu produzieren.

Dies erfordert dann zwar extra Aufwand, um eine Ausgabe zu erzeugen, macht die Funktion aber besser modular nutzbar.

Immerhin tippfreundlicher ist die contains-Version. Allerdings werde ich mir so den egrep-Trick nie merken lernen.

Werbeanzeigen

Kommentar verfassen

Trage deine Daten unten ein oder klicke ein Icon um dich einzuloggen:

WordPress.com-Logo

Du kommentierst mit Deinem WordPress.com-Konto. Abmelden /  Ändern )

Google Foto

Du kommentierst mit Deinem Google-Konto. Abmelden /  Ändern )

Twitter-Bild

Du kommentierst mit Deinem Twitter-Konto. Abmelden /  Ändern )

Facebook-Foto

Du kommentierst mit Deinem Facebook-Konto. Abmelden /  Ändern )

Verbinde mit %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.