Eliminar cadena entre dos patrones de expresiones regulares

Eliminar cadena entre dos patrones de expresiones regulares

Tengo un archivo con el siguiente contenido.

..\..\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

El resultado que espero es

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

¿Cómo puedo lograr esto usando sed?

No puedo escribir una expresión regular para capturar dos grupos al mismo tiempo.

  1. grupo inicial (....\src): será el mismo en todas las líneas
  2. grupo de variables (abc\abc.cpp) o (xyz\xyz.cpp) o (pqr\pqr.cpp) o (pqr\abc.cpp)

Respuesta1

Con BSD sedo versiones recientes de GNU sed(para versiones anteriores, reemplace -Econ -r):

sed -E 's#(.*\\src).*(\\[^\]+\\[^\]+$)#\1\2#' file.txt
  • #se utiliza como delimitador para el scomando de sustitución ( ) de sed, para evitar ambigüedades que involucren \s en la entrada

  • (.*\\src)partidos hasta srcel principio y colocar el partido en el grupo 1 capturado

  • (\\[^\]+\\[^\]+$)coincide con la parte que tiene dos \s hasta el final y se coloca en el grupo capturado 2, lo .*anterior coincide con todo lo que se encuentra entre el primer y segundo grupo capturado

  • En la reposición hemos utilizado los dos grupos capturados.

POSIX-ly:

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

Ejemplo:

% 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

Respuesta2

Soluciones alternativas:

Con GNU grepypaste

grepextrae los dos patrones .*\\srco (\\[^\]+){2}$los imprime en líneas separadas. Luego, la salida se combina usandopaste

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

Conperl

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

Aquí el texto entre los patrones .*\\srcy (\\[^\\]+){2}$se elimina mediante el uso de búsquedas positivas.

Respuesta3

Crear un archivo con datos

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

Ejecute el siguiente comando

[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]$

Respuesta4

¿Por qué atacar esto con expresiones regulares? La modificación de rutas no requiere expresiones regulares; Los kernels del sistema operativo no usan expresiones regulares para seguir rutas.

Con Awk, simplemente usamos barra invertida como separador y los componentes se convierten en campos:

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

información relacionada