Es gibt ein paar wichtige Dinge, die Sie über die [[ ]]
Konstruktion von Bash wissen sollten . Der Erste:
Wortaufteilung und Pfadnamenerweiterung werden für die Wörter zwischen [[
und nicht ausgeführt ]]
. Tilde-Erweiterung, Parameter- und Variablenerweiterung, arithmetische Erweiterung, Befehlssubstitution, Prozessersetzung und Anführungszeichenentfernung werden durchgeführt.
Das zweite:
Ein zusätzlicher binärer Operator, '= ~', ist verfügbar. Die Zeichenfolge rechts neben dem Operator wird als erweiterter regulärer Ausdruck betrachtet und entsprechend abgeglichen. Jeder Teil des Musters kann in Anführungszeichen gesetzt werden, um die Übereinstimmung zu erzwingen als Zeichenfolge .
Folglich wird $v
auf beiden Seiten von =~
auf den Wert dieser Variablen erweitert, aber das Ergebnis wird nicht durch Wörter geteilt oder durch Pfadnamen erweitert. Mit anderen Worten, es ist absolut sicher, variable Erweiterungen auf der linken Seite nicht in Anführungszeichen zu setzen, aber Sie müssen wissen, dass variable Erweiterungen auf der rechten Seite stattfinden.
Wenn Sie also schreiben: [[ $x =~ [$0-9a-zA-Z] ]]
wird das $0
Innere des regulären Ausdrucks rechts erweitert, bevor der reguläre Ausdruck interpretiert wird. Dies führt wahrscheinlich dazu, dass der reguläre Ausdruck nicht kompiliert werden kann (es sei denn, die Erweiterung $0
endet mit einer Ziffer oder einem Interpunktionssymbol, dessen ASCII-Wert kleiner als ist eine Ziffer). Wenn Sie die rechte Seite so zitieren [[ $x =~ "[$0-9a-zA-Z]" ]]
, wird die rechte Seite als gewöhnliche Zeichenfolge behandelt, nicht als regulärer Ausdruck (und $0
wird immer noch erweitert). Was Sie in diesem Fall wirklich wollen, ist[[ $x =~ [\$0-9a-zA-Z] ]]
In ähnlicher Weise wird der Ausdruck zwischen [[
und ]]
in Wörter aufgeteilt, bevor der reguläre Ausdruck interpretiert wird. Leerzeichen in der Regex müssen also maskiert oder in Anführungszeichen gesetzt werden. Wenn Sie Buchstaben, Ziffern oder Leerzeichen abgleichen möchten, können Sie Folgendes verwenden : [[ $x =~ [0-9a-zA-Z\ ] ]]
. Andere Zeichen müssen ebenfalls maskiert werden #
, was einen Kommentar auslösen würde, wenn sie nicht zitiert würden. Natürlich können Sie das Muster in eine Variable einfügen:
pat="[0-9a-zA-Z ]"
if [[ $x =~ $pat ]]; then ...
Für reguläre Ausdrücke, die viele Zeichen enthalten, die maskiert oder in Anführungszeichen gesetzt werden müssten, um durch Bashs Lexer zu gelangen, bevorzugen viele Menschen diesen Stil. Aber Vorsicht: In diesem Fall können Sie die Variablenerweiterung nicht zitieren:
if [[ $x =~ "$pat" ]]; then ...
Schließlich denke ich, dass Sie versuchen zu überprüfen, ob die Variable nur gültige Zeichen enthält. Der einfachste Weg, diese Prüfung durchzuführen, besteht darin, sicherzustellen, dass sie kein ungültiges Zeichen enthält. Mit anderen Worten, ein Ausdruck wie dieser:
valid='0-9a-zA-Z $%&#'
if [[ ! $x =~ [^$valid] ]]; then ...
!
negiert den Test und verwandelt ihn in einen Operator "stimmt nicht überein", und eine [^...]
Regex-Zeichenklasse bedeutet "jedes andere Zeichen als ...
".
Die Kombination von Parametererweiterungs- und Regex-Operatoren kann die Syntax von Bash-regulären Ausdrücken "fast lesbar" machen, aber es gibt immer noch einige Fallstricke. (Gibt es nicht immer?) Einer ist , dass Sie nicht setzen könnten ]
in $valid
, auch wenn $valid
zitiert wurden, außer ganz am Anfang. (Dies ist eine Posix-Regex-Regel: Wenn Sie ]
in eine Zeichenklasse aufnehmen möchten , muss sie am Anfang stehen. Sie -
kann am Anfang oder am Ende stehen. Wenn Sie also beide benötigen ]
und -
, müssen Sie mit beginnen ]
und mit enden -
. was zu dem regulären Ausdruck : „ich weiß , was ich tue“ Emoticon: [][-]
)