Es gibt keinen guten Grund warum
[[ $a = a|b ]]
Sollte einen Fehler melden, anstatt zu testen, ob $ a die a|bZeichenfolge ist[[ $a =~ a|b ]] kein Fehler zurückgegeben wird.
Der einzige Grund ist, dass |im Allgemeinen (außen und innen [[ ... ]]) ein besonderer Charakter ist. Erwarten Sie an dieser [[ $a =Stelle basheinen Tokentyp, der ein normales WORT ist, wie die Argumente oder Ziele von Umleitungen in einer normalen Shell-Befehlszeile (aber so, als ob die extglobOption seit Bash 4.1 aktiviert worden wäre).
(Mit WORD beziehe ich mich hier auf ein Wort in einer hypothetischen Shell-Grammatik, wie sie in der POSIX-Spezifikation beschrieben ist. Dies ist etwas, das die Shell als ein Token in einer einfachen Shell-Befehlszeile parsen würde, nicht als andere Definition von Wörtern wie dem Englischen eine aus einer Folge von Buchstaben oder eine Sequenz von nicht-Abstandszeichen. foo"bar baz", $(echo x y)sind zwei solcher WORD s).
In einer normalen Shell-Befehlszeile:
echo a|b
Wird echo azu geleitet b. a|bist kein WORT , es sind drei Token: ein a WORT , ein |Token und ein b WORT- Token.
Wenn in verwendet [[ $a = a|b ]], bashrechnet mit einem WORD , die es bekommt ( a), aber dann findet ein unerwartetes |Token , das den Fehler verursacht.
Interessanterweise bashbeschwert sich nicht in:
[[ $a = a||b ]]
Da es sich jetzt um ein aToken handelt, auf das ein ||Token folgt b, wird es folgendermaßen analysiert:
[[ $a = a || b ]]
Was testet das $aist aoder dass die bZeichenfolge nicht leer ist.
Jetzt in:
[[ $a =~ a|b ]]
bashkann nicht die gleiche Parsing-Regel haben. Dieselbe Parsing-Regel zu haben würde bedeuten, dass das oben Genannte einen Fehler ergibt und dass man dies zitieren muss, |um sicherzustellen, dass es sich um a|bein einziges WORT handelt . Aber seit Bash 3.2, wenn Sie tun:
[[ $a =~ 'a|b' ]]
Das a|bpasst nicht mehr zum regulären Ausdruck, sondern zum a\|bregulären Ausdruck. Das heißt, Shell-Anführungszeichen haben den Nebeneffekt, dass die spezielle Bedeutung von regulären Ausdrücken entfernt wird. Es ist eine Funktion, daher ähnelt das Verhalten [[ $a = "?" ]]demjenigen, aber Platzhaltermuster (verwendet in [[ $a = pattern ]]) sind Shell- WÖRTER (verwendet zum Beispiel in Globs), während reguläre Ausdrücke dies nicht tun.
So müssen bashalle erweiterten Regexp-Operatoren, die ansonsten normalerweise spezielle Shell-Zeichen |sind (, )unterschiedlich behandelt werden, wenn ein Argument der=~ Operators .
Beachten Sie jedoch, dass während
[[ $a =~ (ab)*c ]]
jetzt arbeitet,
[[ $a =~ [)}] ]]
nicht. Du brauchst:
[[ $a =~ [\)}] ]]
[[ $a =~ [')'}] ]]
Welche in früheren Versionen von bashwürde falsch auf Backslash passen. Das war behoben, aber
[[ $a =~ [^]')'] ]]
Stimmt nicht mit Backslash überein, wie es zum Beispiel sein sollte. Da sich das bashnicht in )den Klammern befindet, entgeht das ), was zu einem [^]\)]regulären Ausdruck führt, der für jedes Zeichen außer ], \und passt ).
ksh93 hat viel schlimmere Bugs an dieser Front.
In zsh, es ist eine normale Shell Wort , das erwartet wird , und unter Angabe regexp Betreiber nicht die Bedeutung von regexp Operatoren beeinflussen.
[[ $a =~ 'a|b' ]]
Stimmt mit dem a|bregulären Ausdruck überein.
Das heißt, das =~kann auch zum [/ testBefehl hinzugefügt werden :
[ "$a" '=~' 'a|b' ]
test "$a" '=~' 'a|b'
(auch arbeiten in yash. Die =~muss dort zshals =somethingspezieller Shell-Operator angegeben werden).
Bash 3.1 verwendet, um sich wie zu verhalten zsh. Es wurde in Version 3.2 geändert, vermutlich, um eine Ausrichtung mit ksh93(obwohl bashes sich um die erste Shell handelte [[ =~ ]]), aber Sie können es trotzdem tun BASH_COMPAT=31oder shopt -s compat31zum vorherigen Verhalten zurückkehren (mit der Ausnahme, dass [[ $a =~ a|b ]]in bashVersion 3.1 zwar ein Fehler zurückgegeben wird , dies jedoch nicht mehr der Fall ist in bash -O compat31neueren Versionen von bash).
Ich hoffe, es wird klargestellt, warum ich sagte, dass die Regeln verwirrend waren und warum:
[[ $a =~ $var ]]
Hilft auch bei der Portabilität auf andere Shells.
|Besonderes ist) standardmäßig rechts von aktiviert ist[[ $var = $pattern ]]. Es wäre interessant, die Versionen undshoptOptionskonfigurationen zu isolieren, bei denen dieses Verhalten auftritt. Wenn nur diejenigenextglobaktiviert sind, die entweder standardmäßig oder explizit konfiguriert sind, sind wir hier.