Reputation: 125
I'm triying to find a string in a txt format and each time it's found then look for an specific string to change for another string.
Imagine the next hexa txt:
02 11 86 05 01 01 01 a0 11 60 0f 80 02 07 80 a1
09 06 07 04 00 00 01 00 1d 03 8a 02 01 2a 02 01
b7 09 01 27 30 22 a0 0a 80 08 33 04 03 92 22 14
00 11 86 05 01 01 01 a0 11 60 0f 80 02 07 80 a1
09 06 07 04 00 00 01 00 1d 03 8a 02 01 2a 02 01
b7 09 01 27 30 22 a0 0a 80 08 33 04 03 92 22 14
I need that each time I encounter a 2a sequence to look for 09 01 sequence and replace with 03 02.
Expected output:
02 11 86 05 01 01 01 a0 11 60 0f 80 02 07 80 a1
09 06 07 04 00 00 01 00 1d 03 8a 02 01 2a 02 01
b7 03 02 27 30 22 a0 0a 80 08 33 04 03 92 22 14
00 11 86 05 01 01 01 a0 11 60 0f 80 02 07 80 a1
09 06 07 04 00 00 01 00 1d 03 8a 02 01 2a 02 01
b7 03 02 27 30 22 a0 0a 80 08 33 04 03 92 22 14
Im triying something this:
sed -i 's/09 01\(.*2a\)/03 02/g' packet.txt
Upvotes: 1
Views: 343
Reputation: 58351
This might work for you (GNU sed):
sed -zE 's/^/\x00/ # introduce a unique delimiter
:a;/\x00$/{s///;b} # remove delimiter at end-of-file
/\x002a/!{s/\x00(.)/\1\x00/;ba} # if not 2a pass over next char
s//2a\x00/ # next char is 2a prep for next string
:b;/\x00$/ba # is it end of file
/\x0009(\s)01/{s//03\102\x00/;ba} # replace string and prep for 2a again
s/\x00(.)/\1\x00/;bb' file # not desired string so pass over char
Since the desired string (in this case09 01
) may occur on another line or within in the same line twice or more, line processing is not feasible. Processing must be at character level and in this solution the entire file is processed as one string (see -z
option).
Two cases are identified:
2a
), processing within the place holder :a
.09 01
with 03 02
), processing within the place holder :b
.Once the key is identified, processing passes to the next case. Once the desired string has been replaced, processing is passed back the first case. Either case can terminate processing when the end-of-file is encountered.
N.B. The solution relies on the file not containing the null character hex 00
.
Upvotes: 0
Reputation: 12867
Alternative awk solution using GNU awk:
awk 'BEGIN { RS="2a" } { ORS=RS } $0 ~ /09 01/ { $0=gensub("09 01","03 02","g",$0)}1' file
Set 2a as the record separator. Check each record for "09 01". If it exists, replace "09 01" with "03 02" with the gensub function and set this as $0. Use short hand 1 to print the record after setting the output record separator the same as the record separator.
Upvotes: 0
Reputation: 47089
Assuming you mean: "only replace if it occurs after 2a", then you can do it by transforming the bytes, so that only one 2a
occurs on each line, e.g.:
<hexa.txt tr '\n' ' ' | sed 's/2a/\n&/g'
Now all you need to do is only replace 09 01
when the line starts with 2a
, e.g.:
sed -E 's/(^2a.*) 09 01/\1 03 02/'
Now go back to the original formatting, i.e. 16 bytes per line:
tr '\n' ' ' | xargs -n16
All together:
<hexa.txt tr '\n' ' ' | sed 's/2a/\n&/g' |
sed -E 's/(^2a.*) 09 01/\1 03 02/' |
tr '\n' ' ' | xargs -n16
Output:
02 11 86 05 01 01 01 a0 11 60 0f 80 02 07 80 a1
09 06 07 04 00 00 01 00 1d 03 8a 02 01 2a 02 01
b7 03 02 27 30 22 a0 0a 80 08 33 04 03 92 22 14
00 11 86 05 01 01 01 a0 11 60 0f 80 02 07 80 a1
09 06 07 04 00 00 01 00 1d 03 8a 02 01 2a 02 01
b7 03 02 27 30 22 a0 0a 80 08 33 04 03 92 22 14
Upvotes: 1
Reputation: 76
I would do this with awk:
$ awk ' { for ( i = 1; i <= NF; ++i ) {
if ( $i == "2a" )
r = 1
if ( r && $i == "09" && $(i+1) == "01" ) {
r = 0
$i = "03"
$++i = "02"
}
}
}
1 ' hexa.txt > hexa.txt.modified
Grep the differences:
$ sdiff hexa.txt hexa.txt.modified
02 11 86 05 01 01 01 a0 11 60 0f 80 02 07 80 a1 02 11 86 05 01 01 01 a0 11 60 0f 80 02 07 80 a1
09 06 07 04 00 00 01 00 1d 03 8a 02 01 2a 02 01 09 06 07 04 00 00 01 00 1d 03 8a 02 01 2a 02 01
b7 09 01 27 30 22 a0 0a 80 08 33 04 03 92 22 14 | b7 03 02 27 30 22 a0 0a 80 08 33 04 03 92 22 14
00 11 86 05 01 01 01 a0 11 60 0f 80 02 07 80 a1 00 11 86 05 01 01 01 a0 11 60 0f 80 02 07 80 a1
09 06 07 04 00 00 01 00 1d 03 8a 02 01 2a 02 01 09 06 07 04 00 00 01 00 1d 03 8a 02 01 2a 02 01
b7 09 01 27 30 22 a0 0a 80 08 33 04 03 92 22 14 | b7 03 02 27 30 22 a0 0a 80 08 33 04 03 92 22 14
Upvotes: 2