Modifica di flussi binari contenenti "\ x00" byte


8

Utilizzando solo strumenti di shell, come si può modificare un flusso binario contenente NULL (0x00 caratteri) mantenendo i caratteri 0x00 nel flusso di output?

La modifica deve sostituire un carattere in una posizione specificata con un altro carattere (nel seguente esempio il carattere '|'), come ad esempio:

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

Ma sed sta rimuovendo tutti i caratteri "\ 0x00" prima della sostituzione.

EDIT - Dimostrazione del comportamento sed nel mio ambiente usando il test @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

Il mio ambiente è un AIX 7.1 e il sed che c'è non è la versione gnu.

Risposte:


10

sedè un'utilità di testo . Funziona con righe di testo (sequenze di caratteri non NUL (non byte) di lunghezza limitata delimitata da un carattere di nuova riga).

Se si desidera modificare il 2 ° e 5 ° byte di una sequenza di byte, non funzionerà per diversi motivi:

  • sedfunziona sul testo. Se l'input contiene caratteri NUL, non termina con un carattere di nuova riga, ha più di LINE_MAX byte tra due caratteri di nuova riga, contiene sequenze di byte che non formano caratteri validi, a seconda seddell'implementazione, non funzionerà su tutti. (nota che GNU sednon ha molte di queste limitazioni).
  • anche se quell'input binario sembra formare un testo valido, .corrisponde a caratteri, non a byte, quindi può corrispondere a più di un byte.
  • perché il codice sed viene eseguito per ogni riga dell'input, ciò cambierebbe il secondo e il quinto carattere di ogni riga, non dell'intero input.

Per trattare l'input come array arbitrari di byte (senza la limitazione di byte NUL o le limitazioni di lunghezza), è possibile utilizzare perlinvece:

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

Esempio:

$ 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

Oppure potresti usare una rappresentazione di testo intermedia, come usare viml' xxdhelper:

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

xxd -pfornisce un dump esadecimale con 60 caratteri per riga per impostazione predefinita. Sopra stiamo sostituendo il secondo e il quinto esagono di 2 cifre della prima riga con 7cil numero per ASCII |.


Grazie. Stavo costruendo una soluzione alternativa usando xxd. Grande ! Entrambe le soluzioni hanno funzionato in AIX.
Luciano,

1

Sei sicuro ? con un semplice test questo non sembra accadere nel mio 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

Con ulteriori test, null andrà perso se si sostituisce il sesto carattere nei miei test (posizione null):

$ 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 Vedi aggiornamento
George Vasiliou,

Guarda la mia modifica
Luciano,

@Luciano, ho anche provato con sed --posix che secondo il mio manuale disabilita tutte le estensioni GNU, ma sono ancora presenti byte nulli ....
George Vasiliou,

Ho provato sed in Linux, e sì sembra funzionare. Ma devo farlo funzionare in AIX.
Luciano,

1
@Luciano, Certo, posso capirlo ... Purtroppo non ho AIX per aiutarti, e per quanto ne so sembra che non ci siano AIX Shells online con cui giocare ... Sono sicuro che la risposta di Mr Chazelas ti aiuterà.
George Vasiliou,

0

Prova bbe - sed clone per flussi binari: https://sourceforge.net/projects/bbe/


Potresti aggiungere alcuni dettagli di supporto, come il modo in cui l'utente nel loro ambiente AIX potrebbe usarlo? Inoltre, tieni presente che la domanda dice "Usare solo strumenti di shell", quindi potrebbe essere loro vietato compilare / installare strumenti aggiuntivi,
Jeff Schaller

Sei sicuro di collegare lo strumento giusto? Il tuo link va a un progetto "Block Based Encryption aka 2Bx4Bx2B" aggiornato per l'ultima volta nel 2013
Ale
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.