Como eu usaria o sed para excluir todas as linhas em um arquivo de texto que contenham uma sequência específica?
Como eu usaria o sed para excluir todas as linhas em um arquivo de texto que contenham uma sequência específica?
Respostas:
Para remover a linha e imprimir a saída com a saída padrão:
sed '/pattern to match/d' ./infile
Para modificar diretamente o arquivo - não funciona com o BSD sed:
sed -i '/pattern to match/d' ./infile
O mesmo, mas para o BSD sed (Mac OS X e FreeBSD) - não funciona com o GNU sed:
sed -i '' '/pattern to match/d' ./infile
Para modificar diretamente o arquivo (e criar um backup) - funciona com BSD e GNU sed:
sed -i.bak '/pattern to match/d' ./infile
sed '/pattern to match/d' ./infile > ./newfile
ou se você quiser fazer uma edição no local, pode adicionar a -i
bandeira ao sed como em sed -i '/pattern to match/d' ./infile
. Note que o -i
sinalizador requer GNU sed e não é portátil
sed -i.backup '/pattern to match/d' ./infile
) Isso me levou a fazer edições no local.
sed
os arquivos que não são controlados por versão.
sed -i '' '/pattern/d' ./infile
.
Existem muitas outras maneiras de excluir linhas com sequência específica, além de sed
:
awk '!/pattern/' file > temp && mv temp file
ruby -i.bak -ne 'print if not /test/' file
perl -ni.bak -e "print unless /pattern/" file
while read -r line
do
[[ ! $line =~ pattern ]] && echo "$line"
done <file > o
mv o file
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
sed
exemplo tem um comportamento diferente, apenas greps! deveria ser algo parecido sed -n -i '/pattern/!p' file
.
grep -v "pattern" file > temp; mv temp file
isso pode se aplicar a alguns dos outros exemplos, dependendo do valor de retorno.
seq -f %f 10000000 >foo.txt
. sed d: time sed -i '' '/6543210/d' foo.txt
0m9.294s reais. sed! p: time sed -i '' -n '/6543210/!p' foo.txt
0m13.671s reais. (Para arquivos menores, a diferença é maior.)
Você pode usar o sed para substituir as linhas no lugar de um arquivo. No entanto, parece ser muito mais lento do que usar grep para o inverso em um segundo arquivo e depois 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 três vezes mais na minha máquina.
sed '/pattern/d' filename > filename2; mv filename2 filename
A maneira mais fácil de fazer isso, com o GNU sed
:
sed --in-place '/some string here/d' yourfile
-r
opção (ou -E
, dependendo da sua versão). Isso permite o uso de metacaracteres regex +
, ?
, {...}
e (...)
.
Você pode considerar o uso ex
(que é um editor padrão baseado em comandos do Unix):
ex +g/match/d -cwq file
Onde:
+
executa o comando Ex ( man ex
), o mesmo -c
que o executa wq
(gravar e sair)g/match/d
- Comando Ex para excluir linhas com dados match
, consulte: Potência de gO exemplo acima é um método compatível com POSIX para edição in-loco de um arquivo, de acordo com esta publicação, nas especificações ex
Unix.SE e POSIX .
A diferença sed
é que:
sed
é um editor ED do S tream , não um editor de arquivos. BashFAQ
A menos que você goste de código não transportável, sobrecarga de E / S e outros efeitos colaterais ruins. Então, basicamente, alguns parâmetros (como no local / -i
) são extensões não padrão do FreeBSD e podem não estar disponíveis em outros sistemas operacionais.
man ex
isso me dá o homem para vim
, ao que parece ex
faz parte do vim ... se eu entendi direito que meios a sintaxe padrão para match
é vimregex.com que é semelhante, mas diferente para POSIX e PCRE sabores?
:g
é um comando compatível com POSIX com algumas pequenas diferenças . Presumo que o PCRE tenha sido baseado nisso.
Eu estava lutando com isso no Mac. Além disso, eu precisava fazer isso usando substituição de variável.
Então eu usei:
sed -i '' "/$pattern/d" $file
onde $file
é o arquivo onde a exclusão é necessária e $pattern
é o padrão a ser correspondido para exclusão.
Eu escolhi o ''
deste comentário .
O que deve ser observado aqui é o uso de aspas duplas em "/$pattern/d"
. A variável não funciona quando usamos aspas simples.
sed
requer um parâmetro depois -i
, então se você não quer um backup, você ainda tem que adicionar uma string vazia:-i ''
sed -i "/$pattern/d" $file
. Obrigado pela sua resposta.
Fiz uma pequena referência com um arquivo que contém aproximadamente 345.000 linhas. O caminho com grep
parece ser cerca de 15 vezes mais rápido que o sed
método neste caso.
Eu tentei com e sem a configuração LC_ALL = C, não parece alterar significativamente os tempos. 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
Você também pode usar isso:
grep -v 'pattern' filename
Aqui -v
será impresso apenas outro que não o seu padrão (isso significa correspondência invertida).
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 dos arquivos originais, adicionando .bk aos nomes dos arquivos (.bk pode ser alterado para qualquer coisa).
Caso alguém queira fazer isso para correspondências exatas de strings, você pode usar a -w
flag em grep - w para todo. Ou seja, por exemplo, se você deseja excluir as linhas que têm 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
Também funciona com o -f
sinalizador se você deseja excluir vários padrões exatos ao mesmo tempo. Se "lista negra" for um arquivo com vários padrões em cada linha que você deseja excluir de "arquivo":
grep -w -v -f blacklist file
-w, --word-regexp Select only those lines containing matches that form whole words.
vs-x, --line-regexp Select only those matches that exactly match the whole line. For a regular expression pattern, this is like parenthesizing the pattern and then surrounding it with ^ and $.
cat filename | grep -v "pattern" > filename.1
mv filename.1 filename
para mostrar o texto tratado no console
cat filename | sed '/text to remove/d'
salvar texto tratado em um arquivo
cat filename | sed '/text to remove/d' > newfile
anexar informações de texto tratadas a um arquivo existente
cat filename | sed '/text to remove/d' >> newfile
para tratar o texto já tratado, neste caso, remova mais linhas do que foi removido
cat filename | sed '/text to remove/d' | sed '/remove this too/d' | more
o | more
texto será exibido em pedaços de uma página por vez.
Você pode usar o bom e velho ed
para editar um arquivo de maneira semelhante à resposta usada ex
. A grande diferença nesse caso é que ed
recebe seus comandos por meio da entrada padrão, não como argumentos de linha de comando como ex
pode. Ao usá-lo em um script, a maneira usual de acomodar isso é usar printf
para canalizar comandos para ele:
printf "%s\n" "g/pattern/d" w | ed -s filename
ou com um heredoc:
ed -s filename <<EOF
g/pattern/d
w
EOF