Grep-Regex-Ergebnis nicht wie erwartet?

Grep-Regex-Ergebnis nicht wie erwartet?

Verwendung von FreeBSD 11.1:

#!/bin/sh

if printf 'abcde.fgh' | grep -iEq '^[^][$^*_-]'; then
    echo "test 1 success"
else
    echo "test 1 fail"
fi

echo

if printf 'abcde.fgh' | grep -iEq '^[^][.$^*_-]'; then
    echo "test 2 success"
else
    echo "test 2 fail"
fi

Ausgabe:

test 1 success

grep: Unmatched [ or [^
test 2 fail

Aber soweit ich weiß, sollten diese das gleiche Ergebnis liefern. Sie enthalten beide eine Bedingung für das erste Zeichen (nur), dass es nicht zu einer Liste von angegebenen nicht-alphabetischen Zeichen gehört. Aufschlüsselung des regulären Ausdrucks:

  • ^= Beginn der Zeichenfolge
  • [^...]= Übereinstimmung, wenn keines dieser Zeichen
  • Innerhalb der Liste ]muss das erste Zeichen sein, ^darf nicht das erste sein und - muss das letzte sein. Es handelt sich also ][.^$_-um eine gültige Liste von Literalzeichen und die Zeichenfolge darf keinem davon entsprechen.
  • Um Verwirrung zu vermeiden, beachten Sie, dass dies bedeutet, dass es ][sich um Literale "]"und "["Zeichen in der Liste handelt.nichtein Schließen und erneutes Öffnen von 2 Listen.

Der einzige Unterschied zwischen den beiden Ausdrücken ist, dass "."es sich jedoch um eine Liste handelt, daher sollte es so behandelt werden, not literal .und tatsächlich entspricht das erste Zeichen nicht dem Literal"."

Was übersehe ich? Wahrscheinlich etwas ganz Offensichtliches und Einfaches?

Antwort1

Ihnen fehlen noch ein paar weitere Syntaxregeln. Innerhalb einer Klammererweiterung gibt es neben einfachen Bereichen auch einige Arten von mehrstelligen Ausdrücken, die mit einem beginnen [. (Siehe dieregulärer Ausdruck(7)Handbuch fürLinuxoderFreeBSDbei „Mit Ausnahme dieserund einige Kombinationen mit '['(siehe nächste Absätze)".) Diese sind:

  • Zusammentragende Elemente: [..]
  • Äquivalenzklassen: [==]
  • Charakterklassen: [::]

(Möglicherweise haben Sie Ausdrücke wie [[:digit:]]„Hierbei handelt es sich eigentlich um eine Zeichenklasse [:digit:], die zufällig das einzige Element einer […]Klammererweiterung ist“ gesehen oder verwendet.)

Da die also in Ihrem Fall .unmittelbar nach einem stehen [, werden sie als öffnendes Trennzeichen eines Sortierelements erkannt. GNU grep 3.1 hat die richtige Fehlermeldung:

$ printf 'abcde.fgh' | grep -iEq '^[^][.$^*_-]'
grep: Unmatched [, [^, [:, [., or [=

Mit den gleichen Ausdrücken kann man solchen Situationen aus dem Weg gehen, indem man beispielsweise [...]oder verwendet [=.=], um einen normalen Punkt einzuschließen, oder auf ähnliche Weise, [=-=]um einen Bindestrich anzupassen, wenn es keinen Ort gibt, an den sie verschoben werden können.

verwandte Informationen