Zeichenfolge zwischen zwei Regex-Mustern löschen

Zeichenfolge zwischen zwei Regex-Mustern löschen

Ich habe eine Datei mit folgendem Inhalt

..\..\src\modules\core\abc\abc.cpp
..\..\src\modules\core\something\xyz\xyz.cpp
..\..\src\other_modules\new_core\something\pqr\pqr.cpp
..\..\src\other_modules\new_core\something\pqr\abc.cpp

Das Ergebnis, das ich erwarte, ist

..\..\src\abc\abc.cpp
..\..\src\xyz\xyz.cpp
..\..\src\pqr\pqr.cpp
..\..\src\pqr\abc.cpp

Wie kann ich dies mit sed erreichen?

Ich kann keinen regulären Ausdruck schreiben, um zwei Gruppen gleichzeitig zu erfassen.

  1. anfängliche Gruppe (....\src) - diese ist in allen Zeilen gleich
  2. Variablengruppe (abc\abc.cpp) oder (xyz\xyz.cpp) oder (pqr\pqr.cpp) oder (pqr\abc.cpp)

Antwort1

Mit BSD sedoder neueren Versionen von GNU sed(für ältere Versionen ersetzen Sie es -Edurch -r):

sed -E 's#(.*\\src).*(\\[^\]+\\[^\]+$)#\1\2#' file.txt
  • #swird als Trennzeichen für den Befehl substitution ( ) von verwendet sed, um Mehrdeutigkeiten im Zusammenhang mit \s in der Eingabe zu vermeiden.

  • (.*\\src)Spiele bis srczum Start und lege das Spiel in die erfasste Gruppe 1

  • (\\[^\]+\\[^\]+$)entspricht dem Teil mit zwei \s bis zum Ende und wird in die erfasste Gruppe 2 eingefügt. Das .*vorhergehende this entspricht allem zwischen der ersten und zweiten erfassten Gruppe

  • Beim Ersetzen haben wir die beiden erfassten Gruppen verwendet

POSIX-mäßig:

sed 's#\(.*\\src\).*\(\\[^\]\+\\[^\]\+$\)#\1\2#' file.txt

Beispiel:

% cat file.txt
..\..\src\modules\core\abc\abc.cpp
..\..\src\modules\core\something\xyz\xyz.cpp
..\..\src\other_modules\new_core\something\pqr\pqr.cpp
..\..\src\other_modules\new_core\something\pqr\abc.cpp

% sed -E 's#(.*\\src).*(\\[^\]+\\[^\]+$)#\1\2#' file.txt
..\..\src\abc\abc.cpp
..\..\src\xyz\xyz.cpp
..\..\src\pqr\pqr.cpp
..\..\src\pqr\abc.cpp

Antwort2

Alternative Lösungen:

Mit GNU grepundpaste

grepextrahiert die beiden Muster .*\\srcund (\\[^\]+){2}$gibt sie in getrennten Zeilen aus. Die Ausgabe wird dann kombiniert mitpaste

$ grep -oE '.*\\src|(\\[^\]+){2}$' ip.txt | paste -d '' - -
..\..\src\abc\abc.cpp
..\..\src\xyz\xyz.cpp
..\..\src\pqr\pqr.cpp
..\..\src\pqr\abc.cpp

Mitperl

$ perl -pe 's/.*\\src\K.*(?=(\\[^\\]+){2}$)//' ip.txt 
..\..\src\abc\abc.cpp
..\..\src\xyz\xyz.cpp
..\..\src\pqr\pqr.cpp
..\..\src\pqr\abc.cpp

Hier wird der Text zwischen den Mustern .*\\srcund (\\[^\\]+){2}$durch positive Lookarounds gelöscht.

Antwort3

Erstellen Sie eine Datei mit Daten

-rwxr-xr-x. 1 sasi   webApp  190 Oct  4 13:42 file.txt

Führen Sie den folgenden Befehl aus

[sasi@localhost temp]$ sed -E 's#(.*\\src).*(\\[^\]+\\[^\]+$)#\1\2#' file.txt
..\..\src\abc\abc.cpp
..\..\src\xyz\xyz.cpp
..\..\src\pqr\pqr.cpp
..\..\src\pqr\abc.cpp
[sasi@localhost temp]$
[sasi@localhost temp]$
[sasi@localhost temp]$

Antwort4

Warum sollte man das mit regulären Ausdrücken bearbeiten? Für die Pfadbereinigung sind keine regulären Ausdrücke erforderlich. Betriebssystemkernel verwenden keine regulären Ausdrücke, um Pfaden zu folgen.

Mit Awk verwenden wir einfach einen Backslash als Trennzeichen und Komponenten werden zu Feldern:

awk 'BEGIN { FS = OFS = "\\" } { print $1, $2, $3, $(NF-1), $NF }'

verwandte Informationen