Como encontrar linhas correspondentes a um padrão e excluí-las?


14

Em um arquivo com muitas linhas, quero excluir as linhas que começam com HERE IT IS.

Como posso fazer isso usando apenas ferramentas de linha de comando?


2
Embora um pouco não convencional, você poderia usar vimassim: vim '+g/^HERE IT IS/d' +wq test.txt;)
Doorknob

@ Doorknob, obrigado por apontar isso. Na verdade, eu estou no meu caminho para usar o vim
micgeronimo

Respostas:


28

Tente sed:

sed -i '/^HERE IT IS/d' <file>

AVISO: É melhor fazer um backup ao usar a -iopção de sed:

sed -i.bak '/^HERE IT IS/d' <file>

O arquivo original permanecerá como <file>.bake o arquivo modificado permanecerá <file>.


Como posso colocar o caractere de nova linha após a seqüência correspondente e gravar em nova linha?
micgeronimo

2
sed -i 's/^HERE IT IS/HERE IT IS\n/' <file>
19415 heemayl

1
@micgeronimo: prazer em ajudar. Verifique minhas edições, por favor.
heemayl

6
@micgeronimo tente fazer a pergunta que você realmente deseja que seja respondida na sua pergunta original (lembre-se de que você pode editá-la), e não através de comentários que possam ser limpos / excluídos. Você pode usar sed '/^HERE IT IS/G' file.
steeldriver

1
O uso de sed é muito profissional.
LakshyaAg

18

Além das respostas grepe sedrespostas muito boas que você recebeu, aqui estão outras ferramentas que podem fazer a mesma coisa:

  • Algumas maneiras de Perl:

    perl -ne '/^HERE IT IS/ || print' file > newfile
    perl -ne 'print if !/^HERE IT IS/' file > newfile
    perl -ne 'print unless /^HERE IT IS/' file > newfile
    

    Você pode adicionar a -iopção a qualquer um dos exemplos para editar o arquivo no local:

    perl -i.bak -ne '/^HERE IT IS/ || print' file        
    
  • g) awk

    awk '!/^HERE IT IS/' file > newfile
    

    As versões mais recentes (4.1.1 e posterior) do GNU awk(o padrão awkno Linux) também podem editar o arquivo no local:

    gawk -i inplace  '!/^HERE IT IS/' file
    
  • Shell ( bash, zsh, ksh, provavelmente outros). Isso é meio bobo, porém, pode ser feito, mas outras ferramentas são melhores.

    while IFS= read -r line; do 
      [[ $line =~ ^"HERE IT IS" ]] || printf "%s\n" "$line"
    done < file > newfile
    

1
Você está apenas se exibindo! ;-) (mas você tem um upvote, porque é inteligente e eu aprendi muito e bashum me fez LOL)
Fabby

o bash deve ser usado printf "%s\n" "$line": citando $ line para preservar espaços em branco e evitando alguns problemas de eco (interpretação de caracteres especiais, etc.). e evita a necessidade de adicionar --também.
Olivier Dulac

@OlivierDulac justo o suficiente. Eu não queria complicar as coisas para casos extremos, mas, como a Cuanglm adicionou IFS=e -r, posso muito bem percorrer todo o caminho e torná-la robusta.
terdon

@terdon: ela é tudo para melhor boa ^^ (e eu fiz um já, embora, como ele é muito informativo para iniciantes)
Olivier Dulac

2
@OlivierDulac Posso garantir que, se eu estivesse postando no Unix e Linux , teria usado printf, IFS =, -r e citação :). Costumo simplificar as coisas para o público da UA que geralmente se sentem menos à vontade com a linha de comando.
terdon

13

Eu usaria greppara filtrá-los. Por exemplo :

grep -v "^HERE IT IS" infile > outfile

Em seguida, mova outfile de volta para infile.


Pensamento inteligente
Anwar

5

sed é definitivamente o caminho a percorrer.

Essa ligeira modificação do comando @heemayl forneceu que você exclua a linha, independentemente de o mesmo caso ser usado no padrão ou não, devido ao I na referência do padrão.

sed -i '/HERE IT IS/Id' <file>

Se você tiver vários arquivos em um diretório em que deseja fazer isso, poderá combiná-lo com o achado.

find . -maxdepth 1 -type f -exec sed -i.bak '/HERE IT IS/Id' {} +

A opção maxdepth significa que isso não ocorrerá novamente nos diretórios.


4

Outra opção python:

#!/usr/bin/env python3
[print(l, end = "") for l in open(f).readlines() if not l.startswith("HERE IT IS")]

Onde f é o caminho para o arquivo, entre aspas.


4

Grep

grep -P '^(?!HERE IT IS)' file

(?!HERE IT IS)asserção lookahead negativa que faz com que o mecanismo regex corresponda a todo o limite inicial de linha ( que geralmente é correspondido por^ ) apenas se não for seguido pela stringHERE IT IS

Pitão

#!/usr/bin/python3
import sys
fil = sys.argv[1]
with open(fil) as f:
    for line in f:
        if not line.startswith('HERE IT IS'):
            print(line, end="")

Salve o script em um arquivo, diga script.pye execute-o através do comando abaixo no terminal.

python3 script.py infile

você poderia usar regex lá, tipo [print(l, end = "") for l in open(fil).readlines() if not re.match("HERE IT IS", l)], mas não é muito mais eficiente que startswith. Eu me perguntava como [print(l, end = "") for l in open(f).readlines() if not l.startswith("HERE IT IS")]não produziria a saída em uma lista.
Avinash Raj

A primeira vez que me deparei com isso, parecia estranho para mim. Ele gera um comando de impressão (ou qualquer ação que você queira executar) para todos os itens da lista definida.
27615 Jacob Vlijm

Recuperando-lo, apenas por diversão :)
Jacob Vlijm

1

Você pode usar o Vim no modo Ex:

ex -sc 'g/^HERE IT IS/d' -cx file
  1. g pesquisa global

  2. d excluir

  3. x salvar e fechar

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.