GNU/Linux >> LINUX-Kenntnisse >  >> Linux

Shell-Test, ob eine mehrzeilige Zeichenfolge das angegebene Muster in der letzten Zeile enthält?

Ich möchte feststellen, ob eine mehrzeilige Zeichenfolge mit einer Zeile endet, die ein bestimmtes Muster enthält.

Dieser Code ist fehlgeschlagen, er stimmt nicht überein.

s=`echo hello && echo world && echo OK`
[[ "$s" =~ 'OK$' ]] && echo match

Akzeptierte Antwort:

In bash 3.2 oder höher und wenn die Kompatibilität zu 3.1 nicht aktiviert ist (mit dem compat31 Option oder BASH_COMPAT=3.1 ), Zitieren regulärer Ausdrucksoperatoren (nicht nur mit aber mit einem der bash Anführungszeichen ('...' , "..." , $'...' , $"..." )) ihre besondere Bedeutung entfernt.

[[ $var =~ 'OK$' ]]

Übereinstimmungen nur in Zeichenfolgen, die OK$ enthalten wörtlich (dass $ entspricht einem wörtlichen $ )

[[ $var =~ OK$ ]]

Übereinstimmungen mit Zeichenfolgen, die auf OK enden (das $ ist der RE-Operator, der am Ende der Zeichenfolge passt).

Das gilt auch für in Variablen gespeicherte reguläre Ausdrücke oder das Ergebnis einer Substitution.

[[ $var =~ $regexp ]]   # $var matches $regexp
[[ $var =~ "$string" ]] # $var contains $string

Beachten Sie, dass es umständlich werden kann, da es einige Zeichen gibt, die Sie für die Shell-Syntax in Anführungszeichen setzen müssen (wie Leerzeichen, < , > , & , Klammern, wenn nicht übereinstimmend). Wenn Sie beispielsweise mit .{3} <> [)}]& übereinstimmen möchten Regexp (3 Zeichen gefolgt von einem " <> " , entweder ein ) oder } und ein & ), brauchen Sie so etwas wie:

[[ $var =~ .{3}" <> "[})]& ]]

Wenn Sie Zweifel haben, welche Zeichen in Anführungszeichen gesetzt werden müssen, können Sie immer eine temporäre Variable verwenden. Das bedeutet auch, dass der Code mit bash31 kompatibel wird , zsh oder ksh93 :

pattern='.{3} <> [})]&'
[[ $var =~ $pattern ]] # remember *not* to quote $pattern here

Das ist auch der einzige Weg (abgesehen von der Verwendung des compat31 Option (oder BASH_COMPAT=3.1 )) können Sie die erweiterten Nicht-POSIX-Operatoren der regulären Ausdrücke Ihres Systems verwenden.

Zum Beispiel für < Um als Wortgrenze behandelt zu werden, was in vielen Regexp-Engines der Fall ist, benötigen Sie:

pattern='<word>'
[[ $var =~ $pattern ]]

Tun:

[[ $var =~ <word> ]]

funktioniert nicht als bash behandelt diese als Shell-Quoting-Operatoren und entfernen Sie sie, bevor Sie <word> übergeben in die Regexp-Bibliothek.

Beachten Sie, dass es in ksh93 viel schlimmer ist, wo:

[[ $var =~ "x.*$" ]]

wird zum Beispiel auf whatever-xa* passen aber nicht whatever-xfoo . Das obige Zitieren entfernt die besondere Bedeutung von * , aber nicht zu . noch $ .

Die zsh Das Verhalten ist einfacher:Anführungszeichen ändern dort nicht die Bedeutung von Regexp-Operatoren (wie in bash31), was zu einem vorhersehbareren Verhalten führt (es kann auch PCRE-Regexps anstelle von ERE verwenden (mit set -o rematchpcre). )).

Verwandte:Nautilus-Kontextmenüoption zum Erstellen einer neuen Datei?

yash hat keinen [[...]] konstruieren, aber sein [ builtin hat ein =~ Operator (auch in zsh ). Und natürlich [ Da es sich um einen normalen Befehl handelt, kann das Zitieren die Art und Weise, wie Regexp-Operatoren interpretiert werden, nicht beeinflussen.

Beachten Sie auch, dass genau genommen Ihr $s enthält nicht 3 Zeilen, sondern 2 volle Zeilen gefolgt von einer nicht abgeschlossenen Zeile. Es enthält hellonworldnOK . Im OK$ erweiterter regulärer Ausdruck, der $ -Operator würde nur am Ende der Zeichenfolge übereinstimmen .

In einem dreizeiligen String , wie hellonworldnOKn (was Sie mit der Befehlsersetzung nicht erreichen könnten, da die Befehlsersetzung all entfernt abschließende Zeilenumbrüche), das $ würde nach dem n passen , also OK$ würde nicht übereinstimmen.

Mit zsh -o pcrematch jedoch das $ Übereinstimmungen sowohl am Ende der Zeichenfolge als auch vor dem Zeilenumbruch am Ende der Zeichenfolge, falls vorhanden, da sie den PCRE_DOLLAR_ENDONLY nicht passieren Flag zu pcre_compile . Dies könnte als schlechte Idee angesehen werden, da Variablen in Shells im Allgemeinen kein abschließendes Zeilenumbruchzeichen enthalten, und wenn sie dies tun, möchten wir sie im Allgemeinen als Daten betrachten.


Linux
  1. Fügen Sie nach Musterübereinstimmungen mithilfe von Linux-Shell-Skript mehrere Datenzeilen in eine Datei ein

  2. Cat Zeile X bis Zeile Y in einer riesigen Datei?

  3. Finden Sie die Zeilennummer, die das Muster enthält, mit benutzerdefiniertem Regex-Trennzeichen?

  4. Shell-Test, um ein Muster in einer Zeichenfolge zu finden?

  5. Ersetzen Sie Linien, die einem Muster entsprechen, durch Linien aus einer anderen Datei in der richtigen Reihenfolge?

So kommentieren Sie mehrere Zeilen gleichzeitig im Vim-Editor aus

So löschen Sie mehrere Zeilen in Vim

Wie kann ich in einer Linux-Shell jede Zeile einer mehrzeiligen Zeichenfolge verarbeiten?

Wie verkettet man mehrere Ausgabezeilen zu einer Zeile?

Einfügen mehrerer Zeilen in eine Datei nach einem bestimmten Muster mit Shell-Skript

Wie bearbeite ich vorherige Zeilen in einem mehrzeiligen Befehl in Bash?