Excluir número (s) de linha específico de um arquivo de texto usando sed?
-
22-09-2019 - |
Pergunta
Quero excluir um ou mais números de linha específicos de um arquivo. Como eu faria isso usando sed?
Solução
Se você deseja excluir as linhas 5 a 10 e 12:
sed -e '5,10d;12d' file
Isso imprimirá os resultados na tela. Se você deseja salvar os resultados no mesmo arquivo:
sed -i.bak -e '5,10d;12d' file
Isso vai apoiar o arquivo até file.bak
, e exclua as linhas dadas.
Nota: Os números de linha começam em 1. A primeira linha do arquivo é 1, não 0.
Outras dicas
Você pode excluir uma linha única específica com seu número de linha por arquivo sed -i '33d'
Isso excluirá a linha no número da linha 33 e salvará o arquivo atualizado.
e estranho também
awk 'NR!~/^(5|10|25)$/' file
$ cat foo
1
2
3
4
5
$ sed -e '2d;4d' foo
1
3
5
$
Isso geralmente é um sintoma de um antipulro. A ferramenta que produziu os números de linha pode muito bem ser substituída por uma que exclui as linhas imediatamente. Por exemplo;
grep -nh error logfile | cut -d: -f1 | deletelines logfile
(Onde deletelines
é o utilitário que você está imaginando que precisa) é o mesmo que
grep -v error logfile
Dito isto, se você estiver em uma situação em que realmente precisa executar esta tarefa, pode gerar um simples sed
script do arquivo de números de linha. Com humor (mas talvez um pouco confuso) você pode fazer isso com sed
.
sed 's%$%d%' linenumbers
Isso aceita um arquivo de números de linha, um por linha, e produz, na saída padrão, os mesmos números de linha com d
anexado após cada um. Este é um válido sed
script, que podemos salvar em um arquivo, ou (em algumas plataformas) tubos para outro sed
instância:
sed 's%$%d%' linenumbers | sed -f - logfile
Em algumas plataformas, sed -f
não entende o argumento da opção -
Para significar entrada padrão, para que você precise redirecionar o script para um arquivo temporário e limpá -lo quando terminar, ou talvez substituir o traço solitário por /dev/stdin
ou /proc/$pid/fd/1
Se o seu sistema operacional (ou shell) tiver isso.
Como sempre, você pode adicionar -i
antes de o -f
opção para ter sed
Edite o arquivo de destino, em vez de produzir o resultado na saída padrão. Em *plataformas BSDish (incluindo OSX), você precisa fornecer um argumento explícito para -i
também; Um idioma comum é fornecer um argumento vazio; -i ''
.
Gostaria de propor uma generalização com AWK.
Quando o arquivo é feito por blocos de tamanho fixo e as linhas a serem excluídas são repetidas para cada bloco, o AWK pode funcionar bem de tal maneira
awk '{nl=((NR-1)%2000)+1; if ( (nl<714) || ((nl>1025)&&(nl<1029)) ) print $0}'
OriginFile.dat > MyOutputCuttedFile.dat
Neste exemplo, o tamanho do bloco é de 2000 e eu quero imprimir as linhas [1..713] e [1026..1029].
NR
é a variável usada pelo AWK para armazenar o número da linha atual.%
dá o restante (ou módulo) da divisão de dois números inteiros;nl=((NR-1)%BLOCKSIZE)+1
Aqui escrevemos na variável nl o número da linha dentro do bloco atual. (Veja abaixo)||
e&&
são o operador lógico OU e E.print $0
escreve a linha completa
Why ((NR-1)%BLOCKSIZE)+1:
(NR-1) We need a shift of one because 1%3=1, 2%3=2, but 3%3=0.
+1 We add again 1 because we want to restore the desired order.
+-----+------+----------+------------+
| NR | NR%3 | (NR-1)%3 | (NR-1)%3+1 |
+-----+------+----------+------------+
| 1 | 1 | 0 | 1 |
| 2 | 2 | 1 | 2 |
| 3 | 0 | 2 | 3 |
| 4 | 1 | 0 | 1 |
+-----+------+----------+------------+