Chỉnh sửa luồng nhị phân chứa byte '\ x00'


8

Chỉ sử dụng các công cụ shell, làm thế nào một luồng nhị phân có chứa NULL (0x00 chars) có thể được chỉnh sửa để giữ các ký tự 0x00 trong luồng đầu ra?

Việc chỉnh sửa cần thay thế một char ở một vị trí đã chỉ định cho một char khác (trong ví dụ sau bởi char '|'), như:

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

Nhưng sed đang xóa tất cả các ký tự '\ 0x00' trước khi thay thế.

EDIT - Trình diễn hành vi sed trong môi trường của tôi bằng thử nghiệm @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

Môi trường của tôi là AIX 7.1 và sed không có phiên bản gnu.

Câu trả lời:


10

sedlà một tiện ích văn bản . Nó hoạt động với các dòng văn bản (chuỗi các ký tự không phải NUL (không phải byte) có độ dài giới hạn được phân tách bằng ký tự dòng mới).

Nếu bạn muốn thay đổi 2 nd và 5 thứ byte của một chuỗi các byte, nó sẽ không làm việc vì nhiều lý do:

  • sedhoạt động trên văn bản. Nếu đầu vào chứa các ký tự NUL, không kết thúc bằng một ký tự dòng mới, có nhiều hơn LINE_MAX byte ở giữa hai ký tự dòng mới, chứa các chuỗi byte không tạo thành các ký tự hợp lệ, tùy thuộc vào cách sedtriển khai, nó sẽ không hoạt động tại tất cả. (lưu ý rằng GNU sedkhông có nhiều hạn chế đó).
  • ngay cả khi đầu vào nhị phân đó xảy ra để tạo thành văn bản hợp lệ, .khớp với các ký tự, không phải byte, do đó có thể khớp với nhiều hơn một byte.
  • bởi vì mã sed được chạy cho mỗi dòng của đầu vào, điều đó sẽ thay đổi ký tự thứ hai và thứ năm của mỗi dòng, không phải của toàn bộ đầu vào.

Để coi đầu vào là các mảng byte tùy ý (không có giới hạn byte NUL hoặc giới hạn độ dài), bạn có thể muốn sử dụng perlthay thế:

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

Thí dụ:

$ 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

Hoặc bạn có thể sử dụng một đại diện văn bản trung gian, như sử dụng vim's xxdhelper:

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

xxd -ptheo mặc định, kết xuất hex với 60 ký tự trên mỗi dòng. Ở trên, chúng tôi thay thế hex hai chữ số thứ hai và thứ năm của dòng đầu tiên bằng 7c, số cho ASCII |.


Cảm ơn. Tôi đã xây dựng một cách giải quyết bằng xxd. Tuyệt quá ! Cả hai giải pháp đều hoạt động trong AIX.
Luciano

1

Bạn có chắc không ? với một thử nghiệm đơn giản, điều này dường như không xảy ra trong trường hợp của tôi (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

Với thử nghiệm thêm, null sẽ bị mất nếu bạn thay thế ký tự thứ 6 trong các thử nghiệm của tôi (vị trí 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 Xem cập nhật
George Vasiliou

Hãy xem bản chỉnh sửa của tôi
Luciano

@Luciano, tôi cũng đã thử với sed --poseix, theo acc thủ công của tôi sẽ vô hiệu hóa tất cả các phần mở rộng GNU, nhưng vẫn có byte null ....
George Vasiliou

Tôi đã thử sed trong Linux và có vẻ như đang hoạt động. Nhưng tôi cần làm cho nó hoạt động trong AIX.
Luciano

1
@Luciano, Chắc chắn, tôi có thể hiểu điều này ... Thật không may tôi không có AIX để giúp bạn, và theo như tôi biết thì dường như không có AIX Shell trực tuyến để chơi với ... Tôi chắc chắn câu trả lời của Ông Chazelas sẽ giúp bạn.
George Vasiliou

0

Hãy thử bbe - sed clone cho các luồng nhị phân: https://sourceforge.net/projects/bbe/


Bạn có thể thêm một số chi tiết hỗ trợ, chẳng hạn như cách người dùng trong môi trường AIX của họ có thể sử dụng nó không? Ngoài ra, lưu ý rằng câu hỏi cho biết "Chỉ sử dụng các công cụ shell", vì vậy chúng có thể bị hạn chế biên dịch / cài đặt các công cụ bổ sung,
Jeff Schaller

Bạn có chắc chắn rằng bạn đang liên kết đến công cụ phù hợp? Liên kết của bạn đi đến dự án "Mã hóa dựa trên khối hay còn gọi là 2Bx4Bx2B" được cập nhật lần cuối vào năm 2013
Ale
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.