shell - trabalhando - utilizando o sed no linux




Excluir linhas em um arquivo de texto que contenha uma string específica (10)

Como eu usaria o sed para excluir todas as linhas em um arquivo de texto que contenha uma string específica?


A maneira mais fácil de fazer isso, com o GNU sed :

sed --in-place '/some string here/d' yourfile

Apenas no caso de alguém querer fazer isso por combinações exatas de strings, você pode usar o flag -w no grep -w para todo. Ou seja, por exemplo, se você deseja excluir as linhas que possuem o número 11, mas mantenha as linhas com o número 111:

-bash-4.1$ head file
1
11
111

-bash-4.1$ grep -v "11" file
1

-bash-4.1$ grep -w -v "11" file
1
111

Ele também funciona com o sinalizador -f se você quiser excluir vários padrões exatos de uma só vez. Se "lista negra" é um arquivo com vários padrões em cada linha que você deseja excluir do "arquivo":

grep -w -v -f blacklist file

Eu fiz um pequeno benchmark com um arquivo que contém aproximadamente 345 000 linhas. O caminho com o grep parece ser cerca de 15 vezes mais rápido que o método sed neste caso.

Eu tentei tanto com e sem a configuração LC_ALL = C, não parece alterar os horários de forma significativa. A cadeia de pesquisa (CDGA_00004.pdbqt.gz.tar) está em algum lugar no meio do arquivo.

Aqui estão os comandos e os horários:

time sed -i "/CDGA_00004.pdbqt.gz.tar/d" /tmp/input.txt

real    0m0.711s
user    0m0.179s
sys     0m0.530s

time perl -ni -e 'print unless /CDGA_00004.pdbqt.gz.tar/' /tmp/input.txt

real    0m0.105s
user    0m0.088s
sys     0m0.016s

time (grep -v CDGA_00004.pdbqt.gz.tar /tmp/input.txt > /tmp/input.tmp; mv /tmp/input.tmp /tmp/input.txt )

real    0m0.046s
user    0m0.014s
sys     0m0.019s

Existem muitas outras maneiras de excluir linhas com strings específicas além do sed :

AWK

awk '!/pattern/' file > temp && mv temp file

Rubi (1.9+)

ruby -i.bak -ne 'print if not /test/' file

Perl

perl -ni.bak -e "print unless /pattern/" file

Shell (bash 3.2 e posterior)

while read -r line
do
  [[ ! $line =~ pattern ]] && echo "$line"
done <file > o
mv o file

GNU grep

grep -v "pattern" file > temp && mv temp file

E, claro, sed (imprimir o inverso é mais rápido que a exclusão real):

sed -n '/pattern/!p' file

Para remover a linha e imprimir a saída como padrão:

sed '/pattern to match/d' ./infile

Para modificar diretamente o arquivo:

sed -i '/pattern to match/d' ./infile

Para modificar diretamente o arquivo (e criar um backup):

sed -i.bak '/pattern to match/d' ./infile

Para usuários do Mac OS X e FreeBSD:

sed -i '' '/pattern/d' ./infile


Você pode usar sed para substituir linhas no lugar em um arquivo. No entanto, parece ser muito mais lento do que usar grep para o inverso em um segundo arquivo e, em seguida, mover o segundo arquivo sobre o original.

por exemplo

sed -i '/pattern/d' filename      

ou

grep -v "pattern" filename > filename2; mv filename2 filename

O primeiro comando demora 3 vezes mais tempo na minha máquina.


Você também pode usar isto:

 grep -v 'pattern' filename

Aqui -v imprimirá apenas outro que não o seu padrão (isso significa que a correspondência invertida).


cat filename | grep -v "pattern" > filename.1
mv filename.1 filename

perl -i    -nle'/regexp/||print' file1 file2 file3
perl -i.bk -nle'/regexp/||print' file1 file2 file3

O primeiro comando edita o (s) arquivo (s) no local (-i).

O segundo comando faz a mesma coisa, mas mantém uma cópia ou backup do (s) arquivo (s) original (is) adicionando .bk aos nomes dos arquivos (o .bk pode ser alterado para qualquer coisa).







in-place