Editando fluxos binários contendo bytes '\ x00'


8

Usando apenas ferramentas shell, como um fluxo binário contendo NULLs (caracteres 0x00) pode ser editado, mantendo os caracteres 0x00 no fluxo de saída?

A edição precisa substituir um caractere em uma posição especificada por outro caractere (no exemplo a seguir, pelo caractere '|'), como:

dd ibs=1 skip=$offset count=$reglen status=none if=$ARQ |
        sed 's/./\|/2' |
        sed 's/./\|/5' #| more replacements....

Mas o sed está removendo todos os caracteres '\ 0x00' antes da substituição.

EDIT - Demonstração de comportamento sed no meu ambiente usando o teste @George Vasiliou:

$ echo -e "lineA\nlineB\nlineC" | tr '\n' '\0' | od -t x1
0000000 6c 69 6e 65 41 00 6c 69 6e 65 42 00 6c 69 6e 65
0000020 43 00
0000022

$ echo -e "lineA\nlineB\nlineC" | tr '\n' '\0' | sed 's/./|/5' | od -t x1
0000000 6c 69 6e 65 7c 6c 69 6e 65 42 6c 69 6e 65 43
0000017

Meu ambiente é um AIX 7.1 e o sed que existe não é a versão gnu.

Respostas:


10

sedé um utilitário de texto . Funciona com linhas de texto (sequências de caracteres não NUL (não bytes) de comprimento limitado, delimitadas por um caractere de nova linha).

Se você deseja alterar o e o byte de uma sequência de bytes, ele não funcionará por vários motivos:

  • sedtrabalha em texto. Se a entrada contiver caracteres NUL, não terminar em um caractere de nova linha, tiver mais de LINE_MAX bytes entre dois caracteres de nova linha, conter seqüências de bytes que não formam caracteres válidos, dependendo da sedimplementação, não funcionará em todos. (observe que o GNU sednão possui muitas dessas limitações).
  • mesmo que essa entrada binária forme um texto válido, .corresponda a caracteres, não a bytes, portanto, pode corresponder a mais de um byte.
  • porque o código sed é executado para todas as linhas da entrada, isso mudaria o segundo e o quinto caractere de cada linha, não a entrada inteira.

Para tratar a entrada como matrizes arbitrárias de bytes (sem a limitação de bytes NUL ou limitações de comprimento), convém usar perl:

 dd.... | perl -0777 -pe 'for $o (1, 4) {substr($_, $o, 1) = "|"}'

Exemplo:

$ printf 'a\0b\0cd' |
>   perl -0777 -pe 'for $o (1, 4) {substr($_, $o, 1) = "|"}' |
>   od -Ax -tx1 -tc
000000  61  7c  62  00  7c  64
         a   |   b  \0   |   d
000006

Ou você pode usar uma representação de texto intermediária, como vimo xxdassistente de:

dd... | xxd -p | sed '1s/../7c/2;1s/../7c/5' | xxd -p -r

xxd -pfornece um despejo hexadecimal com 60 caracteres por linha por padrão. Acima, estamos substituindo o segundo e o quinto hexágono de 2 dígitos da primeira linha por 7c, o número para ASCII |.


Obrigado. Eu estava criando uma solução alternativa usando o xxd. Ótimo ! Ambas as soluções funcionaram no AIX.
Luciano

1

Você tem certeza ? com um teste simples, isso não parece acontecer no meu caso (gnu sed 4.2.2)

$ echo -e "lineA\nlineB\nlineC"
lineA
lineB
lineC
$ echo -e "lineA\nlineB\nlineC" |tr '\n' '\0'
lineAlineBlineC
$ echo -e "lineA\nlineB\nlineC" |tr '\n' '\0' |sed 's/./|/5'
line|lineBlineC
# Verification if the nulls are still there:
$ echo -e "lineA\nlineB\nlineC" |tr '\n' '\0' |sed 's/./|/5' |tr '\0' '\n'                                                                                                
line|
lineB
lineC

Com mais testes, o nulo será perdido se você substituir o sexto caractere em meus testes (posição nula):

$ echo -e "lineA\nlineB\nlineC" |tr '\n' '\0' |sed 's/./|/6' |tr '\0' '\n'
lineA|lineB 
lineC

$ echo -e "lineA\nlineB\nlineC" |tr '\n' '\0' |sed 's/./|/7' |tr '\0' '\n'
lineA
|ineB           
lineC 

@Luciano See update
George Vasiliou

Veja minha edição
Luciano

@Luciano, eu também tentei com sed --posix que acc aos meus desativa manuais todas as extensões GNU, mas ainda bytes nulos estão presentes ....
George Vasiliou

Eu tentei sed no Linux, e sim parece estar funcionando. Mas preciso fazê-lo funcionar no AIX.
Luciano

1
@ Luciano, claro, eu posso entender isso ... Infelizmente não tenho o AIX para ajudá-lo, e até onde eu sei, parece que não há AIX Shells on-line para brincar ... Tenho certeza que a resposta de O Sr. Chazelas irá ajudá-lo.
George Vasiliou

0

Tente bbe - sed clone para fluxos binários: https://sourceforge.net/projects/bbe/


Você poderia adicionar alguns detalhes de suporte, como como o usuário em seu ambiente AIX pode usá-lo? Além disso, nota que a questão diz "Usar apenas ferramentas de shell", para que eles possam ser impedidos de compilação / instalação de ferramentas adicionais,
Jeff Schaller

Tem certeza de que está vinculando à ferramenta certa? Seu link foi para um projeto "Criptografia baseada em bloco, também conhecido como 2Bx4Bx2B", atualizado pela última vez em 2013
Ale
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.