Eu tenho um arquivo contendo aproximadamente 10 milhões de linhas.
Quero remover todas as linhas do arquivo com menos de seis caracteres.
Como eu faço isso?
command-line
text-processing
Diga-me o porquê
fonte
fonte
Respostas:
Há muitas maneiras de fazer isso.
Usando
grep
:Agora
out.txt
conterá linhas com seis ou mais caracteres.Maneira reversa:
Usando
sed
, removendo linhas de comprimento 5 ou menos:De maneira inversa, imprimindo linhas de comprimento seis ou mais:
Você pode salvar a saída em um arquivo diferente usando o
>
operador comogrep
ou editar o arquivo no local usando a-i
opção desed
:O backup do arquivo original será feito
file.txt.bak
e o arquivo modificadofile.txt
.Se você não deseja manter um backup:
Usando shell, Slower, não faça isso , é apenas para mostrar outro método:
Usando
python
, ainda mais lento do quegrep
,sed
:Melhor compreensão da lista de uso para ser mais pitônico:
fonte
É muito simples:
Isso é extremamente eficiente, pois
grep
não tentará analisar mais do que o necessário, nem interpretar os caracteres de forma alguma: simplesmente envia uma linha (inteira) para stdout (que o shell redireciona para o arquivo de resultados) assim que vê 6 caracteres nessa linha (.
em um contexto regexp corresponde a qualquer caractere 1).Portanto, o grep produzirá apenas linhas com 6 (ou mais) caracteres, e os outros não serão gerados pelo grep, de forma que não resultem no arquivo de resultados.
fonte
Solução 1: usando C
Maneira mais rápida: compile e execute este programa C:
Compile com
gcc program.c -o program
, execute com./program file line_length
(wherefile
= caminho para o arquivo eline_length
= comprimento mínimo da linha, no seu caso6
; o comprimento máximo da linha é limitado a1000000
caracteres por linha; você pode alterar isso alterando o valor deMAX_BUFFER_SIZE
).(Truque para substituir
\n
por\0
encontrado aqui .)Comparação com todas as outras soluções propostas para essa pergunta, exceto a solução shell (teste executado em um arquivo de ~ 91 MB com 10 milhões de linhas com um comprimento médio de 8 caracteres):
Solução # 2: usando AWK:
length>=6
: selength>=6
retornar VERDADEIRO, imprime o registro atual.Solução # 3: usando Perl:
lenght>=6
retornar TRUE, imprime o registro atual.fonte
awk
sed
solução (acontece, eu sei). XDpos
variável? Eu entendo que retorna um ponteiro para o personagemline
com um caractere de nova linha, mas você nunca parece usá-lo. E se você não encontrar, basta configurá-lo para\0
.\0
(strchr()
retorna um ponteiro NULL se o caractere não for encontrado). O ponto é substituir cada nova linha no final de cada linha por,\0
para que a nova linha nunca seja contada porstrlen()
: isto é, para que o comprimento sempre possa ser comparado a 6, independentemente de uma nova linha em falta na última linha. Tratar de maneira diferente apenas a última linha seria muito mais eficiente, eu sei. Provavelmente vou atualizar isso mais tarde.grep
solução no mesmo arquivo e é realmente mais rápido (provavelmente porquestrlen()
não é a melhor ideia aqui) . Vou tentar usar umgetchar()
loop para verificar apenas o primeiro caractere N, acho que isso deve melhorar visivelmente. E sim, qualquer linha acima do comprimento do buffer é simplesmente cortada no comprimento do buffer.Você pode usar o Vim no modo Ex:
\v
ligue magia.{6}
encontre linhas com 6 ou mais caracteresv
seleção invertidad
excluirx
salvar e fecharfonte
Solução Ruby:
Idéia simples: redirecione o arquivo para o stdin do ruby e imprima a linha do stdin apenas se o comprimento for maior ou igual a 6
fonte