How to edit a pcl (binary) file ?

Dear Gurus,

I'm getting a bunch of print spool files in pcl format.
I need to edit them moving graphics to i.e. right to make room for barcode stickers.
I'm trying to run a script in AIX 7.1.0.0 to edit some pcl pointer positions to the right. i.e. change p1018X to p1818X .
Piece of cake.
But.
Our beloved awk, gsub, print will nicely remove also some binary x1B. :eek:
I tried :

awk '{gsub("p1018X","p1818X")} {print $0}' air01.pcl  > air02.pcl

What I get is a (useless) much smaller file:

-rw-rw----           42373 Oct 25 15:56 air01.pcl
-rw-rw-r--           27714 Oct 25 16:43 air02.pcl

I'm about to give up with Aix script for such task.
I know that dd can be used to byte editing, but I never used it.

Shall I call in a C++ programmer ?

Any idea would be greately appreciated. Thanks.

The pcl format uses the escape (ascii 27) as the record separator, it is essentially a binary file. And IMO it is not something you can edit and always get decent results.

I've written simple pcl commands in C programs that do changes to a line of text - like turn on bold.

Download ghostpcl: Note they have linux executables, so you will have to run this on a linux box.
Ghostscript: GhostPCL Downloads

And see if this does what you need. The C++ coder will have to fully understand pcl code in order to make changes. Doesn't sound practical to me.
Ghostscript:ghostpcl lets you manipulate and view files.

awk shouldn't be removing x1b's, but I'd definitely believe it's removing nulls.

Do you have perl?

Or a binary patching with xxd ...
A little tedious, but still good to know ...

# echo "p1018X" | xxd
0000000: 7031 3031 3858 0a                        p1018X.
# echo "p1818X" | xxd
0000000: 7031 3831 3858 0a                        p1818X.

man xxd

vi -b air01.pcl :
(or :set binary if already in)
then
%!xxd Look for 7031 3031 3858 sequence and change it to 7031 3831 3858
Then change reverse
%!xxd -r
Save
:wq!
Handle it manually and become a nerd ! :wink:

@ ctsgnb
sorry but I'm running AIX and xxd is not standard. I'm trying to keep the OS as clean as possible. Furthermore I need to automate the process.

@ Corona688
thanks. Yes I have perl . I understood that awk is a sort of shell, where gsub and print are doing the change and output. So I suppose they are the one messing things up.

I tried with tr . Nice one but it does a byte by byte replacement. I need to search for the whole string. This would be my favourite, if.....

Maybe with od ? I know it is used to 'display' hex code, but I'm not sure it can be used to edit.

Another option could be dd , all examples and tutorial I found are related to changes of file blocks, filesystems etc. So I did not dare to try.

Thanks to keep searching :slight_smile: :slight_smile: :slight_smile:

---------- Post updated at 04:32 PM ---------- Previous update was at 03:56 PM ----------

I don't want to be too optimistic but the following looks working:

perl -i.bak  -p -e 's/p1018X/p1818X/g;' air01.pcl
1 Like

Have you tried the same but replacing the initial string by the same string ?
And then do a binary comparison ?

Just to make sur that the file remain unchanged from a binary point of view...

Perl is specifically designed to be binary-safe and have unlimited line lengths, is the thing. It's better suited to editing binary files than awk.

I bet it was the line lengths that were tripping up awk. On AIX, it'd have a maximum length of 2048 or so, and a binary file would seem to awk as a small number of gigantic lines, newlines appearing anywhere only by coincidence.

1 Like

Yes, the files look unchanged from a binary point of view, same size. Also printout is OK, just the wanted changes, everything else is unchanged.
And yes, the line lenght of my file is huge. awk just goes beserk.

The challenge now is to find&edit a string with both escape char and ascii, i.e.

FIND:
*p1088Y[Esc]*c100g2P

REPLACE with:
*p4088Y[Esc]*c200g2P

where [Esc] is the hex 1B

Thanks.

1 Like

This seems to work:

$ printf "*p1088Y\x1b*c100g2P" | perl -p -e 's/[*]p1088Y\x1b[*]c100g2P/*p4088Y\x1b*c200g2P/g;' | hexdump -C

00000000  2a 70 34 30 38 38 59 1b  2a 63 32 30 30 67 32 50  |*p4088Y.*c200g2P|
00000010

$

The [*] is to make Perl use asterisk as a literal character instead of a wildcard modifier. The second half of the expression is just taken literally anyway.

1 Like

Thanks Corona688!
Tomorrow I will check!

Just like the GNU sed, doesn't it ?

Hi.

If the perl solution from Corona688 works, then use it.

Otherwise here are some alternatives, but unknown if they exist in AIX:

bbe - sed-like editor for binary files
beav - binary editor and viewer
bless - A full featured hexadecimal editor
bvi - binary file editor

dhex - ncurses based hex editor with diff mode
hexer - interactive binary editor with a Vi-like interface
jeex - visual editor to view and edit files in hexadecimal
le - Text editor with block and binary operations

lfhex - large file hex editor
ncurses-hexedit - Edit files/disks in hex, ASCII and EBCDIC
okteta - hexadecimal editor for binary files
radare2 - free and advanced command line hexadecimal editor

shed - A simple hex editor with a pico-style interface
tweak - Efficient text-mode hex editor

Best wishes ... cheers, drl