Regulärer Ausdruck im Bash-Skript

Regulärer Ausdruck im Bash-Skript

Dies ist mein erstes Bash-Skripting, daher mache ich wahrscheinlich leicht einen Fehler.

Im Grunde versuche ich, ein Skript zu schreiben, das die Gruppen eines Benutzers abruft und die Zugehörigkeit zu einer bestimmten Gruppe entsprechend protokolliert. Natürlich wird es noch mehr Funktionen geben, aber es hat keinen Sinn, das zu erstellen, wenn ich nicht einmal den regulären Ausdruck zum Laufen bekomme!

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

Überall, wo ich diesen regulären Ausdruck ausprobiert habe, funktioniert er. Aber im Bash-Skript wird immer nur das ausgegeben $groups, gefolgt von No match. Kann mir also jemand sagen, was daran falsch ist?

Antwort1

Aus man 7 regex:

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

… Um ein wörtliches „-“ einzuschließen, machen Sie es zum ersten oder letzten Zeichen…. [A]lle anderen Sonderzeichen, einschließlich „\“, verlieren innerhalb eines Klammerausdrucks ihre besondere Bedeutung.

Beim Versuch, den regulären Ausdruck mit egrep einzugeben, tritt ein Fehler auf:

$ 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 erzeugt:

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

Da \nichts Besonderes ist, handelt es sich um einen Bereich, genau wie [a-z]wäre. Sie müssen Ihr -am Ende einfügen, 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 (entweder in egrep oder in bash) funktionieren.

bearbeiten:Dies hängt tatsächlich auch von Ihren Gebietsschemaeinstellungen ab. Die Manpage warnt davor:

Bereiche hängen stark von der Sortierreihenfolge ab, portable Programme sollten es vermeiden, sich auf sie zu verlassen.

Zum Beispiel:

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

Auch wenn kein Fehler aufgetreten ist, bewirkt es natürlich nicht das, was Sie möchten:

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

Es ist ein Bereich, der in ASCII die Zeichen \, [, ^, und umfasst _.

Antwort2

Allgemeine Regel bei regulären Ausdrücken (und allen Fehlern in größeren Codeteilen): Reduzieren Sie den Code und bauen Sie ihn schrittweise neu auf oder verwenden Sie die Halbierung – was auch immer für Sie besser funktioniert.

In diesem Fall war der Unterstrich der Übeltäter. Durch das Maskieren mit einem Backslash hat es funktioniert.

verwandte Informationen