Exclui string entre dois padrões de regex

3

Eu tenho um arquivo com o seguinte conteúdo

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

O resultado que estou esperando é

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

Como posso conseguir isso usando sed?

Não consigo escrever uma expressão regular para capturar dois grupos ao mesmo tempo.

  1. grupo inicial (.... \ src) - isso será o mesmo em todas as linhas
  2. grupo de variáveis (abc \ abc.cpp) ou (xyz \ xyz.cpp) ou (pqr \ pqr.cpp) ou (pqr \ abc.cpp)
por dhiraj suvarna 04.10.2016 / 07:18

4 respostas

2

Com BSD sed ou versões recentes do GNU sed (para versões mais antigas, substitua -E por -r ):

sed -E 's#(.*\src).*(\[^\]+\[^\]+$)##' file.txt
  • # é usado como o comando delimitador para substituição ( s ) de sed , para evitar ambigüidade envolvendo \ s na entrada

  • (.*\src) corresponde a src do início e coloca a correspondência no grupo capturado 1

  • (\[^\]+\[^\]+$) corresponde à parte que tem dois \ s até o final e coloca no grupo capturado 2, o .* anterior a isso corresponde a tudo entre o primeiro e o segundo grupos capturados

  • Na substituição, usamos os dois grupos capturados

POSIX-ly:

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

Exemplo:

% 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).*(\[^\]+\[^\]+$)##' file.txt
..\..\src\abc\abc.cpp
..\..\src\xyz\xyz.cpp
..\..\src\pqr\pqr.cpp
..\..\src\pqr\abc.cpp
    
por 04.10.2016 / 07:22
0

Soluções alternativas:

Com o GNU grep e paste

grep extrai os dois padrões .*\src ou (\[^\]+){2}$ e os imprime em linhas separadas. A saída é então combinada usando paste

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

com perl

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

Aqui, o texto entre os padrões .*\src e (\[^\]+){2}$ é excluído usando-se referências positivas

    
por 04.10.2016 / 09:46
0

Crie um arquivo com dados

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

Execute abaixo o comando

[sasi@localhost temp]$ sed -E 's#(.*\src).*(\[^\]+\[^\]+$)##' 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]$
    
por 04.10.2016 / 07:47
0

Por que bater isso com regex? Munging de caminho não requer expressões regulares; Os kernels do sistema operacional não usam expressões regulares para seguir os caminhos.

Com o Awk, usamos apenas a barra invertida como separador e os componentes se tornam campos:

awk 'BEGIN { FS = OFS = "\" } { print $1, $2, $3, $(NF-1), $NF }'
    
por 05.10.2016 / 02:16