Como posso apagar tudo até um padrão e tudo depois de outro padrão de uma linha?

8

No seguinte arquivo:

Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Ut eu metus id lectus vestibulum ultrices. Maecenas rhoncus.

Desejo excluir tudo antes de consectetuer e tudo depois de elit .

Minha saída desejada:

consectetuer adipiscing elit.

Como posso fazer isso?

    
por manuel 15.11.2015 / 22:51

5 respostas

17

Eu usaria sed

sed 's/^.*\(consectetuer.*elit\).*$//' file

Decodificado a sintaxe sed / find / replace /:

  • s/^.* - substitui começando no início da linha ( ^ ) seguido por qualquer coisa ( .* ) até ...
  • \( - inicia um bloco nomeado
  • consectetuer.*elit\. - corresponde à primeira palavra, tudo ( .* ) até a última palavra (neste caso, incluindo o ponto final (escapado)) que você deseja corresponder
  • \) - finaliza o bloco nomeado
  • corresponde a todo o restante ( .* ) ao final da linha ( $ )
  • / - termina a seção de localização substituta
  • - substitua pelo bloco de nome entre o \( e o \) acima
  • / - termina a substituição
por 15.11.2015 / 23:03
4

Se cada linha contiver os padrões inicial e final, a maneira mais fácil de fazer isso é com grep . Em vez de deletar o começo e o final de cada linha, você pode simplesmente enviar o conteúdo entre os dois padrões. A opção -o no GNU grep produz apenas as correspondências:

grep -o 'consectetuer.*elit' file

Nota: como mencionado, isso só funciona se todas as linhas do arquivo puderem ser analisadas dessa maneira. Então, novamente, isso é 80% de todos os casos de uso típicos.

    
por 16.11.2015 / 03:10
1

Dois loops for no AWK:

$ awk '{for(i=1;i<=NF;i++) {if ($i == "consectetuer") beginning=i; if($i== "elit.") ending=i }; for (j=beginning;j<=ending;j++) printf $j" ";printf "\n"   }' file.txt 
consectetuer adipiscing elit.

O gsub do AWK:

$ awk '{gsub(/^.*consectetuer/,"consectetuer"); gsub(/elit.*$/,"elit.");print}' file.txt
consectetuer adipiscing elit.
    
por 15.11.2015 / 23:17
1

Um jeito Perl. Isso é essencialmente o mesmo que resposta sed de MikeV:

perl -pe 's/.*(consectetuer.*elit).*./$1/' file

O -p significa "imprimir todas as linhas depois de aplicar o script fornecido com -e ". O s/foo/bar/ é o operador de substituição; ele substituirá foo por bar . Os parênteses capturam um padrão e nos permitem usá-lo na substituição. O primeiro padrão capturado é $1 , o segundo $2 e assim por diante.

Assim, o comando corresponderá a tudo até consectetuer ( .*consectetuer ), depois tudo até elit ( .*elit ) e depois todo o resto até o final da linha ( .* ) e substituirá isso com o padrão capturado.

    
por 16.11.2015 / 00:07
1

Não sei ao certo por que o título desta pergunta foi editado " do arquivo " para " de uma linha ", enquanto o OP não exclui a possibilidade em vários linhas, embora o exemplo pareça ser apenas uma linha. Seja como for, pode ser útil fornecer uma solução de várias linhas aqui.

Isso funciona para linhas cruzadas:

from1=consectetuer; to2=elit; a="$(cat file)"; a="$(echo "${a#*"$from1"}")"; echo "$from1${a%%"$to2"*}$to2"

Exemplos:

[xiaobai@xiaobai tmp]$ cat file
1
abc consectetuer lsl

home

def elit dd
2 consectetuer ABC elit
[xiaobai@xiaobai tmp]$ from1=consectetuer; to2=elit; a="$(cat file)"; a="$(echo "${a#*"$from1"}")"; echo "$from1${a%%"$to2"*}$to2"
consectetuer lsl

home

def elit
[xiaobai@xiaobai tmp]$ 

referência: Expansão do Parâmetro da Shell

    
por 16.05.2016 / 00:55