Bearbeiten von Binärströmen mit '\ x00'-Bytes

8

Wie kann ein Binärstrom mit NULL-Zeichen (0x00 Zeichen) mit nur Shell-Tools bearbeitet werden, wobei die 0x00-Zeichen im Ausgabestream erhalten bleiben?

Die Bearbeitung muss ein Zeichen an einer bestimmten Position durch ein anderes Zeichen ersetzen (im folgenden Beispiel durch das Zeichen '|'), wie folgt:

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

Aber sed entfernt alle '\ 0x00'-Zeichen vor dem Austausch.

EDIT - Demonstration des Sed-Verhaltens in meiner Umgebung mit dem @ George Vasiliou-Test:

$ 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

Meine Umgebung ist eine AIX 7.1 und das Sed, das es gibt, ist nicht die Gnu-Version.

Luciano
quelle

Antworten:

10

sedist ein Text - Dienstprogramm. Es funktioniert mit Textzeilen (Sequenzen von Nicht-NUL-Zeichen (keine Bytes) begrenzter Länge, die durch ein Zeilenumbruchzeichen begrenzt sind).

Wenn Sie die 2 ändern nd und 5 - ten Byte einer Folge von Bytes, es wird nicht funktionieren aus mehreren Gründen:

  • sedarbeitet an Text. Wenn die Eingabe NUL-Zeichen enthält, nicht mit einem Zeilenumbruchzeichen endet, mehr als LINE_MAX-Bytes zwischen zwei Zeilenumbruchzeichen enthält, Sequenzen von Bytes enthält, die keine gültigen Zeichen bilden, funktioniert dies je nach sedImplementierung nicht alle. (Beachten Sie, dass GNU sednicht viele dieser Einschränkungen hat).
  • Selbst wenn diese Binäreingabe gültigen Text bildet, .stimmt sie mit Zeichen und nicht mit Bytes überein und kann daher mit mehr als einem Byte übereinstimmen.
  • Da der sed-Code für jede Zeile der Eingabe ausgeführt wird, werden das zweite und fünfte Zeichen jeder Zeile und nicht die gesamte Eingabe geändert.

Um Eingaben als beliebige Arrays von Bytes zu behandeln (ohne die NUL-Byte- oder Längenbeschränkung), können Sie perlstattdessen Folgendes verwenden :

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

Beispiel:

$ 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

Oder Sie können eine Zwischentextdarstellung verwenden, z. B. vimden xxdHelfer:

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

xxd -pGibt standardmäßig einen Hex-Dump mit 60 Zeichen pro Zeile aus. Oben ersetzen wir das zweite und fünfte zweistellige Hex der ersten Zeile durch 7cdie Nummer für ASCII |.

Stéphane Chazelas
quelle
Vielen Dank. Ich habe mit xxd eine Problemumgehung erstellt. Großartig ! Beide Lösungen funktionierten in AIX.
Luciano
1

Bist du sicher ? mit einem einfachen Test scheint dies in meinem Fall nicht zu passieren (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

Bei weiteren Tests geht null verloren, wenn Sie das 6. Zeichen in meinen Tests ersetzen (Nullposition):

$ 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 
George Vasiliou
quelle
@ Luciano Siehe Update
George Vasiliou
Schau dir meine Bearbeitung an
Luciano
@ Luciano, ich habe es auch mit sed --posix versucht, das gemäß meinem Handbuch alle GNU-Erweiterungen deaktiviert, aber immer noch null Bytes vorhanden sind ....
George Vasiliou
Ich habe sed unter Linux ausprobiert und es scheint ja zu funktionieren. Aber ich muss es in AIX zum Laufen bringen.
Luciano
1
@ Luciano, klar, ich kann das verstehen ... Leider habe ich kein AIX, um dir zu helfen, und soweit ich weiß, scheint es, dass es keine AIX-Shells gibt, mit denen ich online spielen kann ... Ich bin sicher, die Antwort von Herr Chazelas wird Ihnen helfen.
George Vasiliou
0

Versuchen Sie bbe - sed clone für binäre Streams: https://sourceforge.net/projects/bbe/

user280267
quelle
Könnten Sie einige unterstützende Details hinzufügen, z. B. wie der Benutzer in seiner AIX-Umgebung diese möglicherweise verwendet? Beachten Sie auch, dass in der Frage "Nur Shell-Tools verwenden" steht, sodass sie möglicherweise keine zusätzlichen Tools kompilieren / installieren dürfen.
Jeff Schaller
Sind Sie sicher, dass Sie auf das richtige Tool verlinken? Ihr Link führt zu einem "Block Based Encryption aka 2Bx4Bx2B" -Projekt, das zuletzt 2013 aktualisiert wurde
Ale