Comando shell do Linux para filtrar um arquivo de texto por comprimento de linha

16

Eu tenho uma imagem de disco de 30GB de uma partição borked (acho que dd if=/dev/sda1 of=diskimage ) que eu preciso recuperar alguns arquivos de texto. As ferramentas de criação de dados como foremost funcionam somente em arquivos com cabeçalhos bem definidos, ou seja, não em arquivos de texto simples, por isso recorri ao meu bom amigo strings .

strings diskimage > diskstrings.txt produziu um arquivo de texto de 3gb contendo um monte de seqüências de caracteres, principalmente coisas inúteis, misturadas com o texto que eu realmente quero.

A maior parte do lixo tende a ser um longo e ininterrupto fio de rabiscos. O material que eu estou interessado é garantido para ser menos de 16kb, então eu vou filtrar o arquivo por comprimento de linha. Aqui está o script Python que estou usando para fazer isso:

infile  = open ("infile.txt" ,"r");
outfile = open ("outfile.txt","w");
for line in infile:
    if len(line) < 16384:
        outfile.write(line)
infile.close()
outfile.close()

Isso funciona, mas para referência futura: Existe algum encantamento mágico de uma linha (pense em awk , sed ) que filtraria um arquivo por comprimento de linha?

    
por Li-aung Yip 31.01.2012 / 09:22

4 respostas

26
awk '{ if (length($0) < 16384) print }' yourfile >your_output_file.txt

imprime linhas com menos de 16 kilobytes, como no seu próprio exemplo.

Ou se você gosta do Perl:

perl -nle 'if (length($_) < 16384) { print }' yourfile >your_output_file.txt
    
por 31.01.2012 / 09:29
8

Isso é semelhante à resposta do Ansgar, mas um pouco mais rápido nos meus testes:

awk 'length($0) < 16384' infile >outfile

É a mesma velocidade que as outras respostas do awk. Ele depende do print implícito de uma expressão verdadeira, mas não precisa gastar o tempo para dividir a linha como Ansgar faz.

Observe que o AWK oferece a você if gratuitamente. O comando acima é equivalente a:

awk 'length($0) < 16384 {print}' infile >outfile

Não há if explícito (ou seu conjunto de chaves) como em algumas outras respostas.

Aqui está uma maneira de fazer isso em sed :

sed '/.\{16384\}/d' infile >outfile

ou:

sed -r '/.{16384}/d' infile >outfile

que exclui qualquer linha que contenha 16384 (ou mais) caracteres.

Para fins de conclusão, veja como você usa o sed para salvar linhas maiores que seu limite:

sed '/^.\{0,16383\}$/d' infile >outfile
    
por 31.01.2012 / 17:29
2

Você pode awk , como:

$ awk '{ if (length($0) < 16384) { print } }' /path/to/text/file

Isto imprimirá as linhas mais longas que 16K caracteres (16 * 1024).

Você também pode usar grep :

$ grep ".\{,16384\}" /path/to/text/file

Isso imprimirá as linhas no máximo 16K caracteres.

    
por 31.01.2012 / 09:26
2

Não é realmente diferente das respostas já dadas, mas ainda mais curtas:

awk -F '' 'NF < 16384' infile >outfile
    
por 31.01.2012 / 10:29