Alinhar um arquivo de texto hexadecimal com 9 bytes em cada linha

3

Quero alinhar a parte selecionada de um arquivo de texto em 9 bytes por coluna.

Por exemplo, suponha que meu arquivo de texto se pareça com o seguinte.

00 2f c6 b8 29 fd 02 37 11  00 9f 74 34 0b 60 72 38 20  00 9e 61 33 8e ab 8a c0 09 
00 fa f0 66 6d 0c 44 d6 24 00 a1 11 9d a2 13 a5 b3 83 

Eu quero que o arquivo resultante seja como

00 2f c6 b8 29 fd 02 37 11 
00 9f 74 34 0b 60 72 38 20 
00 9e 61 33 8e ab 8a c0 09 
00 fa f0 66 6d 0c 44 d6 24 
00 a1 11 9d a2 13 a5 b3 83 

Qual é a maneira mais fácil de fazer isso? É possível fazer isso em bash usando sed ou awk talvez?

Ou uma maneira melhor de enquadrar a pergunta é que eu formatei minha sequência de entrada como visto abaixo.

00 88 ec 40 bf 94 1d 63
f4 00 04 1c 4e 06 d0 2c
2e f9 00 90 03 51 d5 71
cc 86 79 00 24 6b 22 30
b6 66 0f 5f 00 c1 cd a5
c8 45 b9 88 85 00 c0 de
ae 47 d9 91 f9 d3 00 5b

Isso é 8 bytes cada linha. Se você observar com cuidado na linha 1, primeiro byte será 00 .na segunda linha, o segundo byte será 00 e na linha 3, o terceiro byte será 00 .Eu quero o alinhamento o arquivo inteiro para que todas as linhas comecem com 00 .hope isso ajuda

    
por liv2hak 25.01.2012 / 22:25

4 respostas

5

Isso funcionará independentemente de quantos bytes estão em uma única linha

sed ':a $!N;s/\n/ /;ta;s/\(\(\([[:xdigit:]]\)\{2\} *\)\{8\}\([[:xdigit:]]\)\{2\}\) */\n/g'

Entrada

$ cat alignbyte
00 2f c6
b8 29 fd 02
37 11 00 9f 74 34 0b 60 72 38
20 00 9e 61 33 8e ab 8a c0 09
00 fa f0 66
6d 0c 44 d6 24
00 a1 11 9d a2 13 a5 b3 83

Saída

$ sed ':a $!N;s/\n/ /;ta;s/\(\(\([[:xdigit:]]\)\{2\} *\)\{8\}\([[:xdigit:]]\)\{2\}\) */\n/g' alignbyte
00 2f c6 b8 29 fd 02 37 11
00 9f 74 34 0b 60 72 38 20
00 9e 61 33 8e ab 8a c0 09
00 fa f0 66 6d 0c 44 d6 24
00 a1 11 9d a2 13 a5 b3 83

Acabei de notar que o seu arquivo de entrada parece ter dois espaços em branco após cada conjunto de 9 bytes, exceto pelo último conjunto. Se isso é um erro de digitação e todos os conjuntos de 9 bytes são de fato separados por dois espaços, então o comando para obter o que você quer é simplesmente isto:

sed 's/  /\n/g' file
    
por 25.01.2012 / 22:36
3

Uma abordagem que não se preocupa com a forma exata da entrada é dividi-la em um item por linha e agrupar itens no número desejado.

tr -s '[:space:]' '\n' |
awk '
    NR % 9 != 1 {printf " "}
    {printf "%s", $0}
    NR % 9 == 0 {print ""}
    END {if (NR % 9) print ""}'

Se você não se importa com um espaço extra no final da linha, você pode simplificar um pouco o código awk :

tr -s '[:space:]' '\n' |
awk '
    {printf "%s ", $0}
    NR % 9 == 0 {print ""}
    END {if (NR % 9) print ""}'

Se a sua entrada não tiver linhas em branco e todos os itens tiverem a mesma largura, existe uma solução mais simples: coloque tudo em uma linha e execute a dobra de linha.

{ tr -s '\n' ' '; echo; } | fold -w 27

Se você tiver o utilitário fmt , ele poderá combinar as duas subtarefas:

fmt -w 27
    
por 26.01.2012 / 02:11
0

Um truque básico:

grep -o ".. .. .. .. .. .. .. .. .." your-file.txt

Se o tamanho das linhas não for múltiplo de 9 hexa bytes, remova o CRCL:

tr -d '\n\r' < your-file.txt | grep -o ".. .. .. .. .. .. .. .. .."

Se o arquivo puder conter espaços consecutivos:

tr -s ' \n\r' ' ' < your-file.txt | grep -o ".. .. .. .. .. .. .. .. .."

Eu aprecio as complexas respostas de programação sed / awk .
Aqui, proponho truques legíveis usando ferramentas básicas.

    
por 25.01.2012 / 22:29
0

Isso pode funcionar em você (na segunda instância em que cada linha tem 8 bytes):

 sed '$!N;s/\n/ /;s/ /\n/9;P;D' file

Na primeira instância (registros de tamanho variável):

fmt -w27 file

Ou com o GNU sed:

sed 'L27;d' file
    
por 26.01.2012 / 14:22