Remover linhas que não começam com um padrão de um determinado conjunto de padrões

10

Eu tenho um arquivo que contém dados como este:

report aaaaaaaa  
-  ..  
-th bbbbbbbbb  
-to ccccccccc

.. --.

Pergunta: desejo remover qualquer linha que não comece com as seguintes seqüências de caracteres:

report  
-th  
-to

isso significa que a saída desejada removerá todos os pontos e hashes do meio indesejados e ficará assim:

report aaaaaaaa  
-th bbbbbbbbb  
-to ccccccccc

sed/ awk/ grep/ etc qualquer solução que funcione.

Rana Khan
fonte

Respostas:

15

Usando sedpara modificar o arquivo no local:

sed -i '/^\(report\|-t\(h\|o\)\)/!d' your_file

Isso instrui seda excluir todas as linhas que não correspondem ao padrão. O padrão em si é ^(início da linha), seguido por um reportou -tseguido por um hou o.

Observe que essa não é uma modificação real no local: sedcria uma cópia de backup temporária e sobrescreve o arquivo original.

Se você deseja sedmanter uma cópia de backup do arquivo original (o que pode ser uma boa idéia se o arquivo contiver dados críticos), ofereça ao -iswitch uma extensão para criar um arquivo de backup:

sed -i'.bak' -e '/^\(report\|-t\(h\|o\)\)/!d' your_file

irá modificar your_filee criar um backup do original chamado your_file.bak.

Uma nota lateral

Por favor, não interprete mal minhas intenções nem se ofenda com isso, mas notei que você tem muitas perguntas semelhantes relacionadas ao regex / processamento de texto. Eu aconselho você a começar a aprender sed, awke grepem seu próprio país para ajudar a acelerar a sua produtividade. Novamente, não me interpretem mal, estou muito feliz em ajudar (como a maioria das pessoas por aqui); acho que você se beneficia enormemente ao escolher essas ferramentas para o seu uso diário.

Apenas para provar como as pessoas são úteis por aqui, considere a sugestão de @ slm nos comentários abaixo e sinta-se à vontade para visitar esta sala de bate-papo a qualquer momento para perguntas.

Joseph R.
fonte
1
Sua expressão regular parece desnecessariamente enigmática. Eu acho que você realmente usa mais caracteres do que se tivesse acabado de listar as três opções explicitamente.
Nispio 6/11
1
@nispio eu sei, mas é provável que seja mais eficiente se o arquivo em questão for grande.
Joseph R.
Interessante. Sempre medi regexps em termos de comprimento ou legibilidade. Nunca pensei muito na velocidade de execução. Acho que não sei o suficiente sobre como elas são avaliadas para julgar o que é rápido, mas presumo que seja uma implementação específica também, certo?
Nispio 6/11
3
Reiterando o que Joseph disse sobre estar disposto a ajudar, se você tiver perguntas gerais que não se encaixam no estilo de perguntas e respostas, sempre tente conversar conosco na sala de bate-papo deste site. chat.stackexchange.com/rooms/26/unix-and-linux . Muitos de nós moramos lá 8-)
slm
@slm Obrigado por isso. Vou adicioná-lo à minha resposta.
Joseph R.
10

Você pode usar grep simples para isso:

$ grep -e '^report\|^-th\|^-to' filename
pradeepchhetri
fonte
1
Não é muita economia, mas você pode combinar o -th/ -tointo -t[ho].
Kevin
grep -eouegrep
Olivier Dulac
2

Usando sed:

sed -n -e '/^report\|^-th\|^-to/p' filename
nispio
fonte
Não é muita economia, mas você pode combinar o -th/ -tointo -t[ho].
Kevin
1
@ Kevin Isso é verdade. Veja minha conversa com Joseph R. nos comentários de sua resposta.
Nispio 6/11
2

Usando awk:

awk '/^report|^-t[ho]/' file
jasonwryan
fonte
Não é muita economia, mas você pode combinar o -th/ -tointo -t[ho].
Kevin
1

O questionador fez dois pontos:

  • desejando remover qualquer linha que não comece com "report" ou "-th" ou "-to".
  • a saída desejada deve remover "todos os pontos e hashes do meio indesejados (sic)"

As soluções, neste momento, abordam o primeiro ponto e, portanto, também o segundo. Mas suponha que o arquivo seja maior e tenha a seguinte aparência:

report aaaaaaaa  
-  ..  
-th bbbbbbbbb  
-to ccccccccc
anything else
.. --.
-tp ddd
-tq eee
     -  -----

Não seria necessário abordar o segundo ponto do OP?

sed -r -i.bak '/^[ |.|-]*$/d' input-file 

faz o trabalho de remover linhas presumivelmente indesejadas contendo apenas espaços, pontos e traços e reter o restante, seja o que for.
Eu pensaria que o risco de qualquer uma das abordagens é que a natureza do arquivo não está definida corretamente.


fonte
0

Usando Perl:

perl -ne 'print if /^report|^-t[ho]/' filename > newfile

ou, editar no local (como sed, perltambém fará um backup temporário, portanto, isso não é verdade na edição no local ):

perl -i.bak -ne 'print if /^report|^-t[ho]/' filename

Isso fará uma cópia do arquivo original chamada filename.bake substituirá o arquivo original pela versão editada.

terdon
fonte