Quero excluir um ou mais números de linha específicos de um arquivo. Como eu faria isso usando o sed?
Quero excluir um ou mais números de linha específicos de um arquivo. Como eu faria isso usando o sed?
Respostas:
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 fará o backup do arquivo file.bak
e excluirá as linhas fornecidas.
Nota: Os números das linhas começam em 1. A primeira linha do arquivo é 1, não 0.
sed -e '5,$d' file
sed -e '5d' file
. A sintaxe é <address><command>
; onde <address>
pode ser uma única linha 5
ou um intervalo de linhas 5,10
, e o comando d
exclui a linha ou linhas especificadas. Os endereços também podem ser expressões regulares ou o cifrão $
indicando a última linha do arquivo.
Você pode excluir uma única linha específica com seu número de linha pressionando
sed -i '33d' file
Isso excluirá a linha no número da linha 33 e salvará o arquivo atualizado.
sed -i '0,/<TARGET>/{/<NEW_VALUE>/d;}' '<SOME_FILE_NAME>'
. Obrigado!
e awk também
awk 'NR!~/^(5|10|25)$/' file
$ cat foo
1
2
3
4
5
$ sed -e '2d;4d' foo
1
3
5
$
Muitas vezes, isso é um sintoma de um antipadrão. A ferramenta que produziu os números das linhas pode muito bem ser substituída por uma que exclua as linhas imediatamente. Por exemplo;
grep -nh error logfile | cut -d: -f1 | deletelines logfile
(onde deletelines
está o utilitário que você imagina 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, poderá gerar um sed
script simples a partir do arquivo de números de linha. Bem humorado (mas talvez um pouco confuso), você pode fazer isso 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 d
anexados após cada um. Este é um sed
script válido , que podemos salvar em um arquivo ou (em algumas plataformas) canalizar para outra sed
instância:
sed 's%$%d%' linenumbers | sed -f - logfile
Em algumas plataformas, sed -f
não entende o argumento de opção -
como entrada padrão, portanto, você deve 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 SO (ou shell ) tem isso.
Como sempre, você pode adicionar -i
antes da -f
opção a sed
edição do arquivo de destino, em vez de produzir o resultado na saída padrão. Nas plataformas * BSDish (incluindo OSX), você também precisa fornecer um argumento explícito -i
; um idioma comum é fornecer um argumento vazio; -i ''
.
p
vez de d
, junto com a opção -n
(não funcionará sem -n
e !d
também não).
Eu gostaria de propor uma generalização com o awk.
Quando o arquivo é criado por blocos de tamanho fixo e as linhas a serem excluídas são repetidas para cada bloco, o awk pode funcionar bem dessa 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 é 2000 e quero imprimir as linhas [1..713] e [1026..1029].
NR
é a variável usada pelo awk para armazenar o número da linha atual.%
fornece 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. (ver abaixo)||
e &&
são o operador lógico OR e AND .print $0
escreve a linha completaWhy ((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 |
+-----+------+----------+------------+