É possível no bash começar a ler um arquivo de um offset de contagem de bytes arbitrários?

18

Eu quero localizar uma data que esteja em algum lugar em um log de 8 GB (texto).

Posso um pouco ignorar uma leitura seqüencial completa, e primeiro fazer divisões binárias do arquivo (tamanho), ou de alguma forma navegar no sistema de arquivos inodes (que eu conheço muito pouco sobre), para começar lendo de cada ponto de divisão, até encontrar um deslocamento adequado de onde começar a minha pesquisa de texto para uma linha cotando a data?

A leitura da última linha de

tail não usa uma leitura sequencial normal, por isso gostaria de saber se este recurso está de alguma forma disponível no bash, ou eu precisaria usar Python ou C / C ++ ... mas eu Estou interessado especificamente em uma opção bash .

    
por Peter.O 02.03.2011 / 05:45

4 respostas

8
for (( block = 0; block < 16; block += 1 ))
do 
    echo $block; 
    dd if=INPUTFILE skip=$((block*512))MB bs=64 count=1 status=noxfer 2> /dev/null | \
        head -n 1
done

que .. não cria arquivos temporários, pula blocos * 512 MB de dados em cada execução, lê 64 bytes dessa posição e limita a saída para a primeira linha dos 64 bytes.

você pode querer ajustar 64 para o que achar necessário.

    
por 02.03.2011 / 07:10
24

Parece que você quer:

tail -c +1048576

ou qualquer número de bytes que você queira pular. O sinal de mais diz a cauda para medir a partir do início do arquivo em vez do fim. Se você está usando a versão GNU do final você pode escrever isso como:

tail -c +1M

Para obter um número fixo de bytes após o corte, em vez de todo o resto do arquivo, basta passar o cursor pela cabeça:

tail -c +1048576 | head -c 1024
    
por 02.03.2011 / 22:21
2

Eu tentaria algo assim para dividir o log em pedaços de 512 MiB para uma análise mais rápida.

split <filename> -b 536870912

Se você estiver procurando o arquivo, o seguinte funcionaria:

for file in x* ; do
  echo $file
  head -n 1 $file
done

Use essa saída para determinar qual arquivo será usado para sua data.

    
por 02.03.2011 / 06:45
0

Aqui está o meu script, eu estou procurando a primeira linha onde o primeiro campo está correspondendo ao meu número. As linhas são classificadas de acordo com o primeiro campo. Eu uso o dd para verificar a primeira linha de blocos de 128K, depois eu pulo para o bloco e faço uma pesquisa. Melhorar a eficiência é o arquivo é mais de 1M.

Qualquer comentário ou correção é apreciado!

#!/bin/bash

search=$1;
f=$2;

bs=128;

max=$( echo $(du $f | cut -f1)" / $bs" | bc );
block=$max;
for i in $(seq 0 $max); do
 n=$(dd bs=${bs}K skip=$i if=$f 2> /dev/null| head -2 | tail -1 | cut -f1)
 if [ $n -gt $search ]; then
  block='expr $i - 1' 
  break;
 fi
done; 
dd bs=${bs}K skip=$block if=$f 2> /dev/null| tail -n +2 | awk -v search="$search" '$1==search{print;exit 1;};$1>search{exit 1;};';

* EDITAR * ** grep é muito mais rápido e ack ainda melhor

    
por 08.02.2014 / 02:55