[SOLVED] How to replace 10th and 11th byte in a hex dump
Linux - NewbieThis Linux forum is for members that are new to Linux.
Just starting out and have a question?
If it is not in the man pages or the how-to's this is the place!
Notices
Welcome to LinuxQuestions.org, a friendly and active Linux Community.
You are currently viewing LQ as a guest. By joining our community you will have the ability to post topics, receive our newsletter, use the advanced search, subscribe to threads and access many other special features. Registration is quick, simple and absolutely free. Join our community today!
Note that registered members see fewer ads, and ContentLink is completely disabled once you log in.
I have a feeling that there is a very simple and efficient solution to my task I simply forgot. If I am wrong and you are a mod would you move this to Programming please?
I am working with hex dump looking like that
Code:
01 74 58 d9 00 1e 4c 08 00 21 85 69 57 40 00 50 ea 74 58 d9 00 5e 6d cb 61 74 31 70 ...
I look for a filter statement to replace the n th byte of a long line of data. I can tell n in advance, but would prefer not to hard code it.
The two -v settings are where you specify the byte number (n) and the replacement byte (new). If you were to put this in a bash script, you could use a syntax like -v n=${byte_number} -v new=${replacement_byte}
The print $0; is in there just to show the "before" value, a debugging check. Remove it after you test.
In fact both the sed as well as the awk example do perform very well, although I have to admit that the sed thing is out of my league. The awk thing rings a bell and looks pretty familiar, so I guess that was, what I had seen before.
Although I already have figured out some ways to automate replacing 4 or 6 byte in a line of hex dump, I assume I am doing things that would let more advanced scripting people run away in sheer terror.
I could pipe things 4 to 6 times, which solves the problem nicely but is anything but high performance...
But those scripts look crude and I would have to write one for each length or go all the way to construct the awk expression depending on a length parameter. Although this sounds mad enough to try once, I don't believe that is the way it is meant to be. So basically what I am still longing for is a way to collapse "-v p1=$1 -v new1=$2 ... p4=$n4 -v new4=$5" to something like "from position n to n+3 replace with something that fits in"
Any suggestions would be highly appreciated.
Regards, Heraton
Last edited by Heraton; 02-18-2012 at 07:10 AM.
Reason: added " \ " to the piping code
(Note that, in this simple case, the redundant pipe to cat has been omitted.)
A more general solution would be to prepare a table of byte numbers and new values, read that in, and then apply it to each line of the input file. (You could even use a three column input table with {byte number, old byte, new byte}, and only replace the bytes when all the old bytes match.) That would be possible as a one-line program, but it would be a long line. Here's such a program written so you could put it in a file, make it executable, and use it as you middle command. (Note that the name of the pattern table is hard codded. It could be passed as a variable, but I was getting lazy.)
N.B.: This is untested code.
Code:
#!/usr/bin/gawk -f
#
# Read in the conversion table
# byte expected_value new_value
# ...
BEGIN {
N=0
while (getline value < "byte_map_table") {
++N
if (n=split(value,Value) != 3) {
printf("Error: Line $d of the byte map table (%s) contained %d values, not three.\n",N,value,n) > "/dev/stderr"
++error
continue
}
Byte[N]=Value[1]
Old[N]=Value[2]
New[N]=Value[3]
}
if (error) exit(1)
}
{
skip=0
for (i in Byte) {
if (Byte[i] < 1 || Byte[i] > NF) {
printf("Warning: Record %d does not contain a byte in column %d. Skipping it.\n", NR, Byte[i]) > /dev/stderr
skip=1
}
if (tolower($i) != tolower(Old[i])) {
printf("Warning: Record %d: Byte %d is %s, not $s. Skipping it.\n",NR,i,$i,Old[i]) > "/dev/stderr
skip=1
}
}
if (!skip) {
for (i in Byte) {
$i=New[i]
}
}
print $0
}
Thank you very much for your answer. Once more your solution is perfectly suitable for my task. For now I'll stick with your first proposal as I need to meet a deadline which expires on Thursday and I am already taking night shifts. But I promise to take a closer look at your second proposal next weekend, as I am sure I can learn quite a lot of that.
Thanks for that advice. I guess I will take a look at that soon. Right now I have to meet a deadline and Perl would not be compatible with my intended audience. Anyway, I guess enlightment is waiting down that road too.
LinuxQuestions.org is looking for people interested in writing
Editorials, Articles, Reviews, and more. If you'd like to contribute
content, let us know.