Dividir dados binários de deslocamento de byte fixo por posição de byte?

3

Eu tenho dados binários que reviso por xxd -ps no formato hexadecimal. Percebo que a distância de byte é 48300 (= 805 * 60) bytes entre dois cabeçalhos onde o separador é fafafafa . Existe o início do arquivo que deve ser ignorado.

Exemplo de dados hexadecimais em que 48300 bytes entre cabeçalhos fafafafa que você pode obter aqui chamado data26.6.2015.txt onde três cabeçalhos e seu binário quase equivalente aqui chamado test_27.6.2015.bin que tem apenas os dois primeiros cabeçalhos. Em ambos os arquivos, os dados do último cabeçalho não são de comprimento completo; caso contrário, você pode assumir que o deslocamento de bytes é fixo, ou seja, o comprimento dos dados entre os cabeçalhos.

Pseudocódigo do algoritmo

  1. procure a posição final do cabeçalho
  2. olhe primeiro duas posições de cabeçalho e defina a diferença dessas posições ( d2 - d1 ) a distância entre eventos; este comprimento do evento é o fixo (777)
  3. dados divididos por posição de byte (777) - TODO devo dividir o formato binário ou como xxd -ps dados convertidos? pela posição do byte (777)

Posso converter os dados de volta para binário por xxd -r como xxd -ps | split and store | xxd -r , mas ainda não tenho certeza se isso é necessário.

Em qual estágio você pode dividir dados binários? Apenas no formato xxd -ps convertido ou como dados binários.

Se dividir no formato xxd -ps convertido, acho que o loop é apenas para o caminho e depois percorre o arquivo. Possíveis ferramentas para dividir csplit , split , ..., não tenho certeza. No entanto, estou incerto.

Saída do grep (ggrep é gnu grep) nos dados hexadecimais

$ xxd -ps r328.raw  | ggrep -b -a -o -P 'fafa' | head
49393:fafa
49397:fafa
98502:fafa
98506:fafa
147611:fafa
147615:fafa
196720:fafa
196725:fafa
245830:fafa
245834:fafa

ao fazer o grep similar no arquivo binário, dando emptyline apenas como uma saída.

$ ggrep -b -a -o '\xfa' r328.raw 

Documentação

A documentação que me foi dada é encontrada aqui e aqui como figura o formato geral de dados SRS:

Em qual estágio você pode dividir dados binários (como dados binários ou como xxd -ps dados convertidos)?

    
por Léo Léopold Hertz 준영 26.06.2015 / 17:22

3 respostas

2

Produz a resposta do meuh meu onde ele usou dados data26.6.2015.txt .

# 1

$ cat 27.6.2015_1.sh && sh 27.6.2015_1.sh 
xxd -r -p <data26.6.2015.txt >/tmp/f1
size=$(stat -c '%s' /tmp/f1)
pat=$(echo -e '\xfa\xfa\xfa\xfa')
set -- 0 $(ggrep -b -a -o "$pat" /tmp/f1 | sed 's/:.*//') $size
i=2
while [ $# -ge 2 ]
do start=$1 end=$2
   let count=$end-$start
   dd bs=1 count=$count skip=$start </tmp/f1 >/tmp/f$i
   let i=i+1
   shift
done
72900+0 records in
72900+0 records out
72900 bytes (73 kB) copied, 0.160722 s, 454 kB/s

# 2

$ cat 27.6.2015_2.sh && sh 27.6.2015_2.sh 
xxd -r -p <data26.6.2015.txt >/tmp/f1
size=$(stat -c '%s' /tmp/f1)
set -- 0 $(ggrep -b -a -o -P '\xfa\xfa\xfa\xfa' /tmp/f1 | sed 's/:.*//') $size
i=2
while [ $# -ge 2 ]
do start=$1 end=$2
   let count=$end-$start
   dd bs=1 count=$count skip=$start </tmp/f1 >/tmp/f$i
   let i=i+1
   shift
done
72900+0 records in
72900+0 records out
72900 bytes (73 kB) copied, 0.147935 s, 493 kB/s

# 3

$ cat 27.6.2015_3.sh && sh 27.6.2015_3.sh 
xxd -r -p <data26.6.2015.txt >r328.raw
tr -d '\n' <data26.6.2015.txt >f1
let size2=2*$(stat -c '%s' f1)
set -- 0 $(ggrep -b -a -o -P 'fafafafa' f1 | sed 's/:.*//') $size2
i=2
while [ $# -ge 2 ]
do  let start=$1/2
    let end=$2/2
    let count=$end-$start
    dd bs=1 count=$count skip=$start <r328.raw  >f$i
    let i=i+1
    shift
done
24292+0 records in
24292+0 records out
24292 bytes (24 kB) copied, 0.088345 s, 275 kB/s
24152+0 records in
24152+0 records out
24152 bytes (24 kB) copied, 0.061246 s, 394 kB/s
24152+0 records in
24152+0 records out
24152 bytes (24 kB) copied, 0.058611 s, 412 kB/s
304+0 records in
304+0 records out
304 bytes (304 B) copied, 0.001239 s, 245 kB/s

A saída é um arquivo hexadecimal e quatro arquivos binários:

$ less f1
$ less f2
"f2" may be a binary file.  See it anyway? 
$ less f3
"f3" may be a binary file.  See it anyway? 
$ less f4
"f4" may be a binary file.  See it anyway? 
$ less f5
"f5" may be a binary file.  See it anyway? 

Deve haver apenas 3 arquivos que possuem fafafafa porque eu só dei três cabeçalhos no arquivo data26.6.2015.txt onde o conteúdo do último cabeçalho é um stubb. Saídas em f2-f5:

$ xxd -ps f2 |head -n3
48000000fe5a1eda480000000d00030001000000cd010000010000000000
000000000000000000000000000000000000000000000100000001000000
ffffffff57ea5e5580510b0048000000fe5a1eda480000000d0003000100
$ xxd -ps f3 |head -n3
fafafafa585e0000fe5a1eda480000000d00030007000000cd0100000200
000000000000020000000000008000000000000000000000000000000000
01000000ffffffff72ea5e55b2eb0900105e000016000000010000000000
$ xxd -ps f4 |head -n3
fafafafa585e0000fe5a1eda480000000d00030007000000cd0100000300
000000000000020000000000008000000000000000000000000000000000
01000000ffffffff72ea5e55f2ef0900105e000016000000010000000000
$ xxd -ps f5 |head -n3
fafafafa585e0000fe5a1eda480000000d00030007000000cd0100000400
000000000000020000000000008000000000000000000000000000000000
01000000ffffffff72ea5e55a9f10900105e000016000000010000000000

onde

  • f1 é o arquivo de dados inteiro data26.6.2015.txt (não é necessário incluir)
  • f2 é o cabeçalho do arquivo, ou seja, o início do arquivo data26.6.2015.txt até o primeiro cabeçalho fafafafa (não é necessário incluir)
  • f3 é o primeiro cabeçalho, correto!
  • f4 é o segundo cabeçalho, correto!
  • f5 é o terceiro cabeçalho, correto!
por 13.04.2017 / 14:36
2

Você pode operar no arquivo binário sem precisar passar pelo xxd. Eu executei seus dados de volta através do xxd e usei grep -b para mostrar o byte offsets do seu padrão (convertido de hex para chars \xfa ) no binário Arquivo.

Eu removi com sed os caracteres correspondentes da saída para deixar apenas os números. Em seguida, defino os argumentos posicionais do shell para os deslocamentos resultantes ( set -- ...)

xxd -r -p <data26.6.2015.txt >/tmp/f1
set -- $(grep -b -a -o -P '\xfa\xfa\xfa\xfa' /tmp/f1 | sed 's/:.*//')

Agora você tem uma lista de compensações em $ 1, $ 2, ... Você pode então extrair a parte que lhe interessa com dd, definindo um bloco tamanho para 1 ( bs=1 ) para que leia byte por byte. skip= diz quantos bytes para pular na entrada e count= o número de bytes para copiar.

start=$1 end=$2
let count=$end-$start
dd bs=1 count=$count skip=$start </tmp/f1 >/tmp/f2

Os trechos acima do início do primeiro padrão até o segundo dia anterior padronizar. Para não incluir o padrão, você pode adicionar 4 para iniciar (e contar reduz em 4).

Se você quiser extrair todas as partes, use um loop em torno desse mesmo código e adicione começando com offset 0 e terminando com offset de tamanho de arquivo na lista de números:

xxd -r -p <data26.6.2015.txt >/tmp/f1
size=$(stat -c '%s' /tmp/f1)
set -- 0 $(grep -b -a -o -P '\xfa\xfa\xfa\xfa' /tmp/f1 | sed 's/:.*//') $size
i=2
while [ $# -ge 2 ]
do start=$1 end=$2
   let count=$end-$start
   dd bs=1 count=$count skip=$start </tmp/f1 >/tmp/f$i
   let i=i+1
   shift
done

Se o grep não funcionar com os dados binários, você poderá usar os dados xxd hex dump. Primeiro remova todas as novas linhas para ter uma linha enorme, então faça o grep usando os valores hexadecimais sem escape, mas então divida todos os deslocamentos por 2, e faça o dd com o arquivo raw:

xxd -r -p <data26.6.2015.txt >r328.raw
tr -d '\n' <data26.6.2015.txt >f1
let size2=2*$(stat -c '%s' f1)
set -- 0 $(grep -b -a -o -P 'fafafafa' f1 | sed 's/:.*//') $size2
i=2
while [ $# -ge 2 ]
do  let start=$1/2
    let end=$2/2
    let count=$end-$start
    dd bs=1 count=$count skip=$start <r328.raw  >f$i
    let i=i+1
    shift
done
    
por 27.06.2015 / 08:19
1

Não é tão difícil assim: apenas procure pela sua sequência inicial e nomeie e corresponda à sua sequência final. Caso contrário, tente pelo menos se aproximar. Você realmente não precisa de todo esse hexadecimal, mas de usá-lo:

fold -w2 <hexfile |
sed -e:t -e's/[[:xdigit:]]\{2\}$/\x&/
    /f[af]$/N;/\(.\)..$/!s/.*\n/&\x/;t
    /^.*\(.\)\(\n.*\)\n\(.*\n\).*/!bt
    s// H_E_A_D  E_N_D /
    s/.* f//;s/a E.*//'

Isso obterá um único código de bytes hexadecimal por linha - cada prefixo w / \x - para cada byte em hexfile exceto onde os códigos de bytes fa ou ff ocorrem 4 vezes em sequência. Nesse caso, ele receberá um marcador H_E_A_D ou E_N_D , em que a string H_E_A_D substituirá a última de quatro \xfa strings e a sequência E_N_D substituirá a primeira das quatro seqüências \xff seqüenciais - o que também deve manter os offsets de byte sincronizados por número de linha.

Assim:

PIPELINE | grep -C8n _

OUTPUT:

(aparado um pouco)


72596-\x8b
72597-\xfa
72598-\xfa
72599-\xfa
72600: H_E_A_D
72601-\x58
--
72660-\x00
72661: E_N_D
72662-\xff
72663-\xff
72664-\xff
72665-\x72

E assim você pode passar a saída do comando acima para, por exemplo:

fold ... | sed ... | grep -n _

... para obter uma lista de deslocamentos em que os cabeçalhos podem começar, terminar. Com o% GNUgrep, você pode usar a opção -A fter para informar quantos bytes deseja ver na sequência contextual - e, por exemplo, talvez queira usar -A777 . Você pode pegar a saída desse jeito e passar:

... | grep -A777 E_N_D | sed -ne's/\/&&/p' | xargs printf %b

... para reproduzir cada byte binário para cada sequência e pode especificar o número da correspondência com -m[num] .

    
por 27.06.2015 / 19:08