
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.
- grupo inicial (....\src): será el mismo en todas las líneas
- grupo de variables (abc\abc.cpp) o (xyz\xyz.cpp) o (pqr\pqr.cpp) o (pqr\abc.cpp)
Respuesta1
Con BSD sed
o versiones recientes de GNU sed
(para versiones anteriores, reemplace -E
con -r
):
sed -E 's#(.*\\src).*(\\[^\]+\\[^\]+$)#\1\2#' file.txt
#
se utiliza como delimitador para els
comando de sustitución ( ) desed
, para evitar ambigüedades que involucren\
s en la entrada(.*\\src)
partidos hastasrc
el 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 capturadoEn 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 grep
ypaste
grep
extrae los dos patrones .*\\src
o (\\[^\]+){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 .*\\src
y (\\[^\\]+){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 }'