Nesta resposta ( como posso remover a primeira linha de um arquivo com sed? ), Há duas maneiras de excluir o primeiro registro em um arquivo:
sed '1d' $file >> headerless.txt
** ---------------- OU ---------------- **
tail -n +2 $file >> headerless.txt
Pessoalmente, acho que o tail
opção é cosmeticamente mais agradável e mais legível, mas provavelmente porque sou desafiada por sed.
Qual método é o mais rápido?
sed
é mais portátil: "+2" paratail
funciona bem no Ubuntu, que usa o GNUtail
, mas não funciona no BSDtail
.tail
falta de compatibilidade entre plataformas.-n
opção e usava a sintaxetail +2 $file
. Veja freebsd.org/cgi/… É possível que você estivesse pensando nisso, e não em um dos BSDs modernos.Respostas:
Desempenho de
sed
vs.tail
para remover a primeira linha de um arquivoTL; DR
sed
é muito poderoso e versátil, mas é isso que o torna lento, especialmente para arquivos grandes com muitas linhas.tail
faz apenas uma coisa simples, mas que faz bem e rápido, mesmo para arquivos maiores com muitas linhas.Para arquivos pequenos e médios,
sed
etail
está executando de maneira semelhante rápida (ou lenta, dependendo de suas expectativas). No entanto, para arquivos de entrada maiores (vários MBs), a diferença de desempenho aumenta significativamente (uma ordem de magnitude para arquivos na faixa de centenas de MBs), comtail
desempenho claramente superior.sed
.Experimentar
Preparações Gerais:
Nossos comandos para analisar são:
Observe que estou canalizando a saída para
/dev/null
cada momento para eliminar a saída do terminal ou as gravações de arquivo como gargalo de desempenho.Vamos configurar um disco RAM para eliminar a E / S do disco como gargalo em potencial. Eu pessoalmente tenho uma
tmpfs
montada,/tmp
então simplesmente coloquei a minhatestfile
lá para este experimento.Depois, estou criando um arquivo de teste aleatório contendo uma quantidade especificada de linhas
$numoflines
com comprimento e dados aleatórios usando este comando (observe que definitivamente não é o ideal, fica muito lento para cerca de> 2 milhões de linhas, mas quem se importa, não é o coisa que estamos analisando):Oh, aliás. meu laptop de teste está executando o Ubuntu 16.04, 64 bits em uma CPU Intel i5-6200U. Apenas para comparação.
Cronometrando arquivos grandes:
Configurando uma enorme
testfile
:A execução do comando acima
numoflines=10000000
produziu um arquivo aleatório contendo 10 milhões de linhas, ocupando um pouco mais de 600 MB - é enorme, mas vamos começar com isso, porque podemos:Execute a execução cronometrada com nosso enorme
testfile
:Agora vamos fazer apenas uma única execução cronometrada com os dois comandos primeiro para estimar com que magnitude estamos trabalhando.
Já vemos um resultado realmente claro para arquivos grandes,
tail
é uma magnitude mais rápida quesed
. Mas apenas por diversão e para ter certeza de que não há efeitos colaterais aleatórios fazendo uma grande diferença, vamos fazer isso 100 vezes:A conclusão permanece a mesma,
sed
é ineficiente para remover a primeira linha de um arquivo grande,tail
deve ser usada lá.E sim, eu sei que as construções de loop do Bash são lentas, mas estamos fazendo relativamente poucas iterações aqui e o tempo que um loop simples leva não é significativo em comparação com os
sed
/tail
durações de qualquer maneira.Cronometrando arquivos pequenos:
Configurando um pequeno
testfile
:Agora, para concluir, vejamos o caso mais comum de você ter um pequeno arquivo de entrada no intervalo de kB. Vamos criar um arquivo de entrada aleatória
numoflines=100
, parecido com este:Execute a execução cronometrada com nosso pequeno
testfile
:Como podemos esperar que o tempo para esses arquivos pequenos esteja no intervalo de alguns milissegundos de experiência, vamos fazer 1000 iterações imediatamente:
Como você pode ver, os horários são bastante semelhantes, não há muito o que interpretar ou pensar. Para arquivos pequenos, ambas as ferramentas são igualmente adequadas.
fonte
awk
pode fazer isso. Minha pergunta original foi baseada no link que encontrei em primeiro lugar. Depois de todo o seu trabalho árduo, informe se devo removerawk
como candidato à solução e retornar o foco ao escopo original do projetosed
e somentetail
.awk 'NR > 1'
, curiosamente).Aqui está outra alternativa, usando apenas bash builtins e
cat
:$file
é redirecionado para o{ }
agrupamento de comandos. Oread
simplesmente lê e descarta a primeira linha. O restante do fluxo é então canalizado para ocat
qual o grava no arquivo de destino.No meu Ubuntu 16.04, o desempenho disso e a
tail
solução são muito semelhantes. Eu criei um arquivo de teste largish comseq
:tail
solução:cat
/ braçadeira:No entanto, eu só tenho uma VM do Ubuntu à mão no momento e vi variações significativas no tempo de ambas, embora todas estejam no mesmo estádio.
fonte
tail
mas ainda acho que aread
opção é muito legal.Experimentando meu sistema e prefixando cada comando com
time
, obtive os seguintes resultados:sed:
e cauda:
o que sugere que, no meu sistema, pelo menos, o AMD FX 8250 executando o Ubuntu 16.04, a cauda é significativamente mais rápida. O arquivo de teste tinha 10.000 linhas com um tamanho de 540k. O arquivo foi lido de um disco rígido.
fonte
sed
pode desempenhar um fator nesse resultado, é a ordem em que você os testou.sed
foi duas vezes mais rápido.Não há uma maneira objetiva de dizer o que é melhor, porque
sed
etail
não são as únicas coisas executadas em um sistema durante a execução do programa. Muitos fatores, como E / S de disco, E / S de rede, CPU interrompem para processos de maior prioridade - todos influenciam a rapidez com que seu programa será executado.Ambos são escritos em C, portanto, este não é um problema de idioma, mas mais um problema ambiental. Por exemplo, eu tenho SSD e no meu sistema isso levará tempo em microssegundos, mas para o mesmo arquivo no disco rígido, levará mais tempo porque os HDDs são significativamente mais lentos. Portanto, o hardware também desempenha um papel nisso.
Lembre-se de algumas coisas ao considerar qual comando escolher:
sed
é um editor de fluxo para transformar texto.tail
é para gerar linhas de texto específicas. Se você quiser lidar com linhas e imprimi-las apenas, usetail
. Se você deseja editar o texto, usesed
.tail
tem uma sintaxe muito mais simples do quesed
, portanto, use o que você pode ler e o que os outros podem ler.Outro fator importante é a quantidade de dados que você está processando. Arquivos pequenos não oferecem diferença de desempenho. A imagem fica interessante quando você lida com arquivos grandes. Com um BIGFILE.txt de 2 GB, podemos ver que
sed
há muito mais chamadas do sistema do quetail
e é consideravelmente mais lento.fonte
tail
melhor do quesed
- use isso. Eu pessoalmente usaria,python
ouawk
melhor,sed
porque pode ficar complexo. Além disso, se você está preocupado com o desempenho, vamos encarar a realidade - você está vendo resultados em microssegundos aqui. Você não sentirá diferença, a menos que seja um arquivo enorme no intervalo de gigabytes que você está tentando ler #awk
resposta:) ... Minha pergunta foi baseada em outra sessão de perguntas e respostas da UA (no link) e nunca foi mencionadaawk
. Concordo que a diferença horária é nominal em arquivos pequenos. Eu estava apenas tentando desenvolver alguns bons hábitos.awk 'NR!=1' input_file.txt
. Dá-me igualmente o mesmo resultado, cerca de 150 milissegundos, mesmo número para ambostail
esed
. Mas, de novo, eu estou usando SSD, então eu diria que é o disco rígido e a CPU que importam, não o comando.sed
demoram mais de 3 minutos, enquanto sãotail
necessários apenas 20 segundos. Isso não é que grande ainda, na verdade, definitivamente não é na faixa GB.A resposta principal não levou em consideração o disco
> /dev/null
se você tem um arquivo grande e não deseja criar uma duplicata temporária no seu disco, tente
vim -c
Editar: se o arquivo for maior que a memória disponível
vim -c
não funcionar, parece que não é inteligente o suficiente para fazer uma carga incremental do arquivofonte
Outras respostas mostram bem o que é melhor criar um novo arquivo com a primeira linha ausente. Se você quiser editar um arquivo em vez de criar um novo arquivo, aposto
ed
que seria mais rápido, porque não deveria criar um novo arquivo. Mas você precisa pesquisar como remover uma linhaed
porque eu a usei apenas uma vez.fonte