2017-12-05 3 views
1

Für einen bestimmten Pfad möchte ich einen bestimmten regulären Ausdruck in alle Dateien in diesem Pfad oder in die Unterverzeichnisse dieses Pfads mit einem vorgegebenen Text unter Verwendung von Standard-Linux-Shell-Befehlen einschließen.Rekursives Umbrechen eines regulären Ausdrucks mit gegebenem Text

Genauer gesagt, wickeln alle meine Syslog-Befehle mit einem Assert-Befehl wie syslog(LOG_INFO,json_encode($obj)); wird assert(syslog(LOG_INFO,json_encode($obj)));.

Ich dachte, das folgende könnte funktionieren, aber sed: -e expression #1, char 47: Invalid preceding regular expression Fehler erhalten.

sed -i -E "s/(?<=syslog\()(.*)(?=\);)/assert(syslog(\1));/" /path/to/somewhere 

BACKUP INFO IN REAKTION AUF Wiktor Stribiżew Antwort

Ich habe sed noch nie benutzt. Bitte bestätigen Sie mein Verständnis für Ihre Antwort:

sed -i "s/syslog(\(.*\));/assert(syslog(\1));/g" /path/to/somewhere 
  • -i Bearbeiten von Dateien an seinem Platz. Man könnte zuerst auslassen, um auf dem Bildschirm zu sehen, was geändert wird.
  • s Ersatztext
  • Die drei / ist, das Muster und den Ersatz umgebenden (d.h. /pattern/replacement/) sind deliminator und kann jede einzelne Zeichen und nicht nur / sein.
  • syslog(\(.*\)); Das Muster mit einem Platzhalter. Verwendet ausgelassene Klammern.
  • assert(syslog(\1)); Die Ersetzung mit Escapezeichen 1 (oder 2, 3 usw.) für Ersatz Sub-Strings.
  • g Ersetzen Sie alle und nicht nur die erste Übereinstimmung.

Würde sed -i "s/syslog(.*);/assert(&);/g" /path/to/somewhere auch funktionieren?

Antwort

1

sed Muster unterstützen keine Lookarounds wie (?<=...) und (?=...).

Sie können eine Erfassungsgruppe/Ersatz Rückreferenzierung verwenden:

sed -i "s/syslog(\(.*\));/assert(syslog(\1));/g" /path/to/somewhere 

Das Muster ist von BRE POSIX Geschmack (keine -E Option übergeben wird), so eine Erfassungsgruppe Sie entkam Klammern verwenden müssen definieren, und Unausgeglichene werden mit wörtlichen Klammern übereinstimmen.

Einzelheiten

  • syslog( - syslog( Teilzeichenfolge
  • \(.*\) - Gruppe 1: alle 0+ chars so viele wie möglich
  • ); - eine ); Teilzeichenfolge

Der Ersatz ist assert(syslog(\1));, das heißt, das Spiel wird ersetzt durch assert(syslog(, den Inhalt der Gruppe 1 und dann ));.

+0

Dank Wiktor. Habe noch nie 'sed' benutzt. Bitte sehen Sie meine bearbeitete Originalfrage und bestätigen Sie, ob sie korrekt ist. Danke – user1032531

+0

Wird das auch nur für die einzelne reguläre Datei '/ path/to/somewhere' funktionieren? Was ist, wenn '/ path/to/somewhere' ein Verzeichnis war und ich wollte, dass es auf alle Dateien in diesem und den Unterverzeichnissen angewendet wurde? – user1032531

+0

Ah, wie ich sehe. 'finde ~/test -type f -print0 | xargs -0 sed -i "s/syslog (\ (. * \));/assert (syslog (\ 1));/g" '. Trotzdem möchten Sie, dass Ihre Kommentare zu meiner bearbeiteten Frage auf Ihre Antwort antworten. – user1032531

0

Wenn Sie Perl-kompatible Regex-Konstrukte benötigen, können Sie Perl (sic) verwenden.

Unabhängig von dieser spezifischen Lösung wechselte ich auf einfache Anführungszeichen unter der Annahme, dass Sie auf einer Unix-ish-Plattform sind. Backslashes in doppelten Anführungszeichen sind lästig (manchmal müssen Sie sie verdoppeln, manchmal nicht).

Perl bevorzugt $1 über \1 im Ersatzmuster, obwohl letzteres auch technisch funktionieren wird.

+0

Für Ihr spezifisches Problem kann die Regex leicht zu einem ERE oder sogar BRE Regex ohne Lookbehinds etc. refaktoriert werden. Wenn Ihre Anforderungen komplexer sind, oder Sie einfach nicht die Unterschiede zwischen den Regex-Dialekt lernen wollen Sie (anscheinend) wissen und eine Reihe von anderen, vielleicht kann dies helfen. – tripleee

Verwandte Themen