
Wenn Sie diesen Code nehmen:
echo -e '\t\t\tString' | grep '^[\t]*String'
das Ergebnis ist leer, da es nicht übereinstimmt, dennoch dies:
echo -e '\t\t\tString' | grep $'^[\t]*String'
funktioniert. Ich schwöre, dass ich den Code der ersten Zeile hundertmal in meinen Skripten und im Terminal verwendet habe, ohne jemals das Zeichen „$“ auf diese Weise zu verwenden, und es schien immer zu funktionieren. Gab es kürzlich eine Änderung? Warum wird das Zeichen „$“ benötigt? Oder mache ich etwas falsch?
Antwort1
ANSI-C-Zitate
Laut Bash-Handbuch heißt dasANSI-C-ZitatIm Handbuch steht:
Wörter der Form$'Zeichenfolge'werden speziell behandelt. Das Wort wird zu einer Zeichenfolge erweitert, wobei durch Backslash maskierte Zeichen gemäß dem ANSI-C-Standard ersetzt werden.
In der Praxis bedeutet dies, dass '\t'
nicht in ein Tabulatorzeichen erweitert wird, sondern $'\t'
wird. Die Ausgabe sollte der Verwendung von entsprechen echo -e
, kann aber überall dort verwendet werden, wo Sie eine Zeichenfolge verwenden würden, ohne dass dies erforderlich ist.Befehlsersetzung.
Dienstprogramme wie GNU sed führen ihre eigene Erweiterung von Escape-Zeichen durch, GNU grep jedoch nicht. Die Bash-Shell, nicht grep, erweitert Escape-Zeichen innerhalb von ANSI-C-Anführungszeichen. Ohne die ANSI-C-Anführungszeichen enthält der von Ihnen gepostete reguläre Ausdruck keine Tabulatorzeichen, die mit der Eingabe übereinstimmen.
Antwort2
Ihnen sollte klar sein, dass es nicht nur einen einzigen Typ regulärer Ausdrücke gibt. Es gibt mindestens basic regular expressions
oder BRE
(manchmal nur RE
), extended regular expressions
oder ERE
und perl compatible regular expressions
oder PCRE
. Alle diese Sprachen verwenden leicht unterschiedliche Syntax. Aktuelle Versionen von GNU grep
unterstützen alle drei und die BRE
sind Standard. Für ERE
müssen Sie -E
die Option und für PCRE
-P
die Option verwenden. Ihr Beispiel funktioniert nur mit , -P
da der Backslash bei einfachem und erweitertem regulären Ausdruck seine Bedeutung verliert und [\t]
entweder mit dem Backslash oder dem Zeichen t übereinstimmt. Sie haben dieses Muster wahrscheinlich in einer anderen Sprache verwendet, die standardmäßig unterstützt wird PCRE
, was Sinn macht, da dies die leistungsstärkste Version ist. Oder vielleicht hatten Sie es alias grep='grep -P'
irgendwo.
Antwort3
Die erste Zeile funktioniert, wenn Sie das weglassen ^
. Vielleicht hat es funktioniert, aber nicht so, wie Sie es erwartet haben? Ich bezweifle, dass grep
sich das Verhalten von in einem so wichtigen Punkt geändert hat.
echo
übersetzt standardmäßig keine Escape-Sequenzen. -e
Dafür benötigen Sie das . Ähnlich verhält es sich mit der Shell. Sie müssen $'...'
die Shell dazu bringen, Escape-Sequenzen zu verwenden.