How to make a valid input for "xxd -r" in vim when removing a byte?

3.1k views Asked by At

Create a file named as test containing the following content:

0123456789abcdef0123456789abcdef

I want to remove the first 0 with the use of xxd. Open it with vim -b test then run :%!xxd inside vim. The result is:

0000000: 3031 3233 3435 3637 3839 6162 6364 6566  0123456789abcdef
0000010: 3031 3233 3435 3637 3839 6162 6364 6566  0123456789abcdef
0000020: 0a                                       .      

Then I remove the hex code 30 for the first 0:

0000000: 31 3233 3435 3637 3839 6162 6364 6566  0123456789abcdef
0000010: 3031 3233 3435 3637 3839 6162 6364 6566  0123456789abcdef
0000020: 0a                                       .

Then I run :%!xxd -r to read the hex back. The result is:

^@23456789abcdef^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@^@

The result is garbled. I know that the reason is the above content is not a valid xxd input. If I remove the line numbers and the text part:

31 3233 3435 3637 3839 6162 6364 6566
3031 3233 3435 3637 3839 6162 6364 6566  
0a  

The I run :%!xxd -r -p to read the hex back. And the result is correct:

123456789abcdef0123456789abcdef

Is there a better way to do this job with the use of vim and xxd? A better way means less editing to make a valid input for xxd -r.

1

There are 1 answers

0
Ben On BEST ANSWER

You've discovered on your own that removing the byte offset column and text column allows you to use :%!xxd -r -p to get what you want. So how about creating a custom command to remove those columns and then do the conversion? :%!xxd -r -p is too much to type, anyway.

Something like:

:command MyXXDR %s#^[^:]*: \(\%(\x\+ \)\+\) .*#\1# | %!xxd -r -p

This exact command may cause problems if you have messed up the format of the file too much with your edits (i.e. if the substitute command doesn't match to remove the necessary text), but you get the idea.