Regulärer Ausdruck im Bash-Skript

13

Dies ist mein erstes Bash-Scripting, daher mache ich wahrscheinlich einen leichten Fehler.

Grundsätzlich versuche ich, ein Skript zu schreiben, das die Gruppen eines Benutzers abruft, und wenn sie sich in einer bestimmten Gruppe befinden, wird dies entsprechend protokolliert. Offensichtlich wird es mehr Funktionalität geben, aber es hat keinen Sinn, etwas aufzubauen, wenn ich nicht einmal den regulären Ausdruck zum Laufen bringen kann!

Bisher habe ich Folgendes:

#!/bin/bash

regex="^([a-zA-Z0-9\-_]+ : [a-zA-Z0-9\-_]+) (usergroup)$"

# example output
groups="username : username usergroup"

echo "$groups" >> /home/jrdn/log

if [[ "$groups" =~ $regex ]]; then
    echo "Match!" >> /home/jrdn/log
else
    echo "No match" >> /home/jrdn/log
fi

Jeder Ort, an dem ich dieses Regex ausprobiert habe, funktioniert. Im Bash-Skript wird jedoch immer nur das ausgegeben $groups, gefolgt von No match. Kann mir jemand sagen, was daran falsch ist?

jrdn
quelle
1
Was lässt Sie denken, dass etwas daran falsch ist?
Manatwork
1
@jrdnhannah dann versuchen Sie langsam, Ihre Ziel-Regexp neu zu erstellen, stimmen Sie zuerst überein, ^([a-zA-Z0-9\-_]+)fügen Sie dann den Doppelpunkt hinzu und so weiter ... Sie sollten ziemlich bald herausfinden, wo das Problem liegt.
Peterph
2
Gleiches hier mit bash 4.2.45. Es wurde behoben, dass der Unterstrich ausgeblendet wurde. Seltsam. @jrdnhannah könntest du das als Antwort aufschreiben und es bitte annehmen?
Terdon
1
Da ich mich gerade erst bei der Unix SE angemeldet habe, muss ich 8 Stunden warten, bevor ich meine Antwort geben kann. Ich bin froh, es als beantwortet markieren zu können, wenn es jemand anderes tut.
3.
4
@terdon bash ruft wahrscheinlich nur die regulären Ausdrücke von libc auf. Es hängt also von der libc-Version ab, nicht von der bash-Version. Siehe meine Antwort ... (oder vielleicht sogar die
Sortierfolge, die

Antworten:

14

Von man 7 regex:

Ein Klammerausdruck ist eine Liste von Zeichen, die in "[]" eingeschlossen sind. …

... Um ein wörtliches '-' einzufügen, machen Sie es zum ersten oder letzten Zeichen ... [A] Alle anderen Sonderzeichen, einschließlich '\', verlieren innerhalb eines Klammerausdrucks ihre besondere Bedeutung.

Wenn Sie den regulären Ausdruck mit egrep versuchen, wird ein Fehler ausgegeben:

$ echo "username : username usergroup" | egrep "^([a-zA-Z0-9\-_]+ : [a-zA-Z0-9\-_]+) (usergroup)$"
egrep: Invalid range end

Hier ist eine einfachere Version, die auch einen Fehler gibt:

$ echo 'hi' | egrep '[\-_]'
egrep: Invalid range end

Da \ist nichts besonderes, das ist eine Reichweite, genau wie [a-z]es sein würde. Sie müssen Ihre -am Ende setzen, wie [_-]oder:

echo "username : username usergroup" | egrep "^([a-zA-Z0-9_-]+ : [a-zA-Z0-9_-]+) (usergroup)$"
username : username usergroup

Dies sollte unabhängig von Ihrer libc-Version funktionieren (entweder in egrep oder bash).

Bearbeiten: Dies hängt auch von Ihren Ländereinstellungen ab. Die Manpage warnt davor:

Bereiche hängen stark von der Sortierreihenfolge ab, und tragbare Programme sollten sich nicht darauf verlassen.

Beispielsweise:

$ echo '\_' | LC_ALL=en_US.UTF8 egrep '[\-_]'
egrep: Invalid range end
$ echo '\_' | LC_ALL=C egrep '[\-_]'
\_

Natürlich macht es nicht das, was Sie wollen, obwohl es keinen Fehler gemacht hat:

$ echo '\^_' | LC_ALL=C egrep '^[\-_]+$'
\^_

Es ist ein Bereich, der in ASCII enthält \, [, ^, und _.

derobert
quelle
Interessant. Meine egrepgibt keinen Fehler, stimmt einfach richtig überein.
Manatwork
@ Manatwork Ihre Sortierfolge erlaubt wahrscheinlich den Bereich ....
Derobert
Ich weiß nicht viel über Kollation. Du meinst das LC_COLLATE="en_US.UTF-8":?
Manatwork
@manatwork Ich habe die Frage bearbeitet, um ein Beispiel zu geben. Beachten Sie, dass dies auf Ihrem System möglicherweise anders ist, da sich diese Sortierfolgen manchmal ändern.
Derobert
1
@manatwork Es ist in Ordnung, ich hätte fast einen Fehlerbericht eingereicht, bevor ich den Fluchtversuch bemerkte -...
derobert
4

Allgemeine Regel bei regulären Ausdrücken (und allen Fehlern in größeren Codeteilen): Reduzieren Sie diese und erstellen Sie sie Schritt für Schritt neu oder verwenden Sie die Halbierung - was auch immer für Sie besser funktioniert.

In diesem Fall stellte sich heraus, dass der Schuldige der Unterstrich ist - ein Fluchtpunkt mit einem Backslash hat es geschafft.

peterph
quelle