I have a string like this:
33 00 4b 46 ff ff 03 10 30 t=25562
I am only interested in the five digits at the very end after the t=
How can I get this numbers with a regular expression out of it?
I tried grep t=..... but I also got all characters including the t= in the beginning, which I would like to drop?
After finding that five digit number, I would like to divide this by 1000. So in the above mentioned case the number 25.562. Is this possible with grep and regular expressions?
Thanks for your help.
Using awk
echo '33 00 4b 46 ff ff 03 10 30 t=25562' | awk -F= '{print $2/1000}'
Output:
25.562
EDIT
As pointed out by #anubhava in comment, above assumes = is not present anywhere before t=. If that's not the case,
echo '33 00 4b 46 ff ff 03 10 30 t=25562' | awk -F' t=' '{print $2/1000}'
This should be OK. It will only get value form t= at the end. OP also post that t= could exist as extra character in the middle of the line, but hi only like to get the one at the end of the line.
echo '33 00 4b 46 ff ff t=22 03 10 30 t=25562' | awk '{split($NF,a,"=");print a[2]/1000}'
25.562
Another variation
echo '33 00 4b 46 ff ff t=22 03 10 30 t=25562' | awk 'END {print $0/1000}' RS==
25.562
Related
This question already has answers here:
How to exclude several lines around match with grep or similar tool?
(2 answers)
Closed 8 years ago.
I would like to grep a pattern and remove the line of the matching pattern and also 1 line before and 4 lines after the context. I tried:
grep -v -A 4 -B 1
Thanks in advance!
Example:
Rule: r1
Owner: Process explorer.exe Pid 1544
0x01ec350f 8b 45 a8 0f b6 00 8d 4d a8 ff 14 85 c8 7f ed 01 .E.....M........
0x01ec351f 84 c0 75 ec 8b 4d fc e8 ba f5 fe ff f7 85 b0 fd ..u..M..........
0x01ec352f ff ff 00 00 01 00 75 13 33 c0 50 50 50 68 48 28 ......u.3.PPPhH(
0x01ec353f eb 01 33 d2 8b cb e8 b0 57 ff ff f7 05 8c 9b ed ..3.....W.......
I would like to grep "explorer.exe" and remove the line and also 1 line before and 4 lines after.
awk
this awk one-liner would help:
awk 'NR==FNR{if(/explorer[.]exe/)d[++i]=NR;next}
{for(x=1;x<=i;x++)if(FNR>=d[x]-1&&FNR<=d[x]+4)next}7' file file
see this example:
kent$ cat f
foo
foo2
Rule: r1
Owner: Process explorer.exe Pid 1544
remove1
remove2
remove3
remove4
bar
bar2
kent$ awk 'NR==FNR{if(/explorer[.]exe/)d[++i]=NR;next}{for(x=1;x<=i;x++)if(FNR>=d[x]-1&&FNR<=d[x]+4)next}7' f f
foo
foo2
bar
bar2
vim
if vim is also possible for you, it could be a lot easier:
:g/Pattern/norm! k6dd
Note, the vim solution would have problem in first match if your pattern was on the 1st line in your file.
I’m trying to fix an encoding error in an archived html page. My problem is that sed is behaving strangely, as it doesn't catch special characters in the data. I tried both with and without -r switch.
My data is the following:
Budapesti ??p?t?©szeti Filmnapok k??l??nkiad??s
The sed command:
sed -i.bak 's|Budapesti.*|REPLACE|g' index.html
and the result I get without recode:
REPLACE�t?�szeti Filmnapok k??l??nkiad??s
The result I'm expecting is:
REPLACE
It seems to be related to the encoding somehow. If I do recode iso-8859-2 index.html first, sed works fine and gets me the expected output.
Here are the hex bytes for the i ??p?t?Šs part before recode:
69 20 3F 3F 70 3F AD 74 3F A9 73
and after recode:
69 20 3F 3F 70 3F C2 AD 74 3F C5 A0 73
BTW, this is what I get without recode:
REPLACEt?Šs
52 45 50 4C 41 43 45 AD 74 3F A9 73
I'm using the latest gsed (GNU sed) 4.2.2.
LANG=C.ISO-8859-2 sed -i.bak 's|Budapesti.*|REPLACE|g' index.html
Cygwin terminal not displaying certain characters?
When i install Sublime Text 2 in my system(Debian) i need to use ghex to find the address 0x590ADC with Edit->Goto Byte. After that, i need replace the number 33 for 32. All this to solve a problem with backspace key.
So, i would like to know if there is other way to do that without using ghex, i would like to do that using command line(sed maybe) because i use a bashscript to install all my system, including softwares like Sublime Text 2.
Bellow, a sed command that replaces all occurrences of 33 42 and replaces for 32 42.
sed 's/\x33\x42/\x32\x42/g' sublime_text
I need something like above, but in a specific address, and 42 is not necessary anymore.
Thank you!
Using bash and dd:
#!/bin/bash
function replace {
[[ $# -eq 4 && -f $1 ]] || return 1
local FILE=$1 ADDRESS=$2 EXPR=$3 LENGTH=$4
local BLOCK_SIZE=512
local BLOCKS=$(( ADDRESS / BLOCK_SIZE ))
local REM=$(( ADDRESS - (BLOCKS * BLOCK_SIZE) ))
{
[[ BLOCKS -gt 0 ]] && dd bs="$BLOCK_SIZE" count="$BLOCKS" status=none
[[ REM -gt 0 ]] && dd bs=1 count="$REM" status=none
printf "$EXPR"
dd bs=1 count="$LENGTH" of=/dev/null status=none
dd bs="$BLOCK_SIZE" status=none
} < "$FILE"
}
Example data (hexdump -C format):
00000000 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f |................|
00000010 10 11 12 13 14 |.....|
Test:
replace data.bin 10 '\xFF\xFF' 2
Output:
00000000 00 01 02 03 04 05 06 07 08 09 ff ff 0c 0d 0e 0f |................|
00000010 10 11 12 13 14 |.....|
This pattern match 33 and 33 42 also
~s/\x33(\x42)?/\x32$1/g
sed doesn't have byte addressing, but it's easy enough to do this with standard tools.
( cut -b1-5835484 file; printf "%c" 50; cut -b5835486- file )>newfile
Given enough unique context, it is possible to find an expression which probably only matches once in the file (but in the pessimal case, you need the entire file as context) so you can do something like
sed 's/\(\x01\xf3\x29\x02\)\x33\(\x42\x29\xea\x44)/\1\x32\2/' file >newfile
There are also programmable hex editors which allow you to do this with a simple sed-like language with byte addressing. Or if you have a hexdump program which reads its own input to reconstruct a new file, do something like
hexdump file |
sed 's/\(^0x0x590AD0 .. .. .. .. .. .. .. .. .. .. .. .. \)33/\132/' |
hexdump -v >newfile
I am trying to parse the output of the s51 simulator using a bash script and sed. In a first step I want one single string containing all the bytes in hexadecimal form. The output of the simulator looks like this. The real output can be much longer, up to 64k.
0x0000 10 11 12 13 14 15 16 17 ........
0x0008 18 19 00 00 00 00 00 00 ........
0x0010 00 00 00 00 00 00 00 00 ........
0x0018 00 00 00 00 00 00 00 00 ........
0x0020 00 00 00 00 00 00 00 00 ........
0x0028 00 00 00 00 00 00 00 00 ........
0x0030 00 00 00 00 00 00 00 00 ........
timer #0("time") ON: 0.001085 sec (13020 clks)
timer #0("isr") ON,ISR: 0 sec (0 clks)
timer #0("idle") ON,ISR: 0 sec (0 clks)
My code to parse is the following:
sed -e ':loop' -e 's/\s\([0-9a-f]\{1\}\)\([0-9a-f]\{1\}\)/\2\1/g' -e 't loop' -n -e 's/.*\(0x[0-9a-f]\{4\}\)\([0-9a-f]\{16\}\).*/\2/p' | sed -e ':a;N;$!ba;s/\n//g'
The first 3 parts swap the two digits of each byte and removes the space. The 4th part removes the other lines and the address and ascii representation. The last part removes the connects the lines.
This outputs a string likes this:
01112131415161718190000000....
I was wondering what I could do better.
This might work for you (GNU sed):
sed '/^0x\S\{4\}\(\( \S\S\)\{8\}\).*/{s//\1/;H};$!d;x;s/\n//g;s/ \(.\)\(.\)/\2\1/g' file
or (at a pinch):
sed -r '/^0x....(( ..){8}).*/{s//\1/;H};$!d;x;s/\n//g;s/ (.)(.)/\2\1/g' file
I think the following should be equivalent:
sed -n -e '/^0x[0-9a-f]\{4\}/H' -e '${x;s/\n\S*//g;s/\s\.\.*//g;s/\s\([0-9a-f]\)\([0-9a-f]\)/\2\1/g;p}'
Or if your version of sed doesn't support separating commands with ;:
sed -n -e '/^0x[0-9a-f]\{4\}/H' -e '${x
s/\n\S*//g
s/\s\.\.*//g
s/\s\([0-9a-f]\)\([0-9a-f]\)/\2\1/g
p
}'
This works by adding each byte line to the hold space, and then when we get to the last line of the file swap the hold and pattern spaces to process them all at once. Then the steps are to remove the newlines and address from beginning of each line, remove the trailing dots (maybe this isn't actually necessary, depending on actual output), and finally swap the digits of each byte and print.
Depending on what version of Linux you are running, there are tools like od or hexdump that can help with this. hexdump is even highly configurable with a sort of mini-script language to control how many bytes get formatted in what way and so on...
One way using GNU awk:
awk '/^0x/ { for (i=2; i<=NF; i++) { gsub(/[^0-9]/,"", $i); line=line $i } } END { printf "%s\n", substr(line,2) }' file.txt
How do I create a .gif file from the following HEX stream:
0d 0a 0d 0a 47 49 46 38 39 61 01 00 01 00 80 ff 00 ff ff ff 00 00 00 2c 00 00 00 00 01 00 01 00 00 02 02 44 01 00 3b
3b is the GIF file terminator
I'm trying to do it following the guide at http://en.wikipedia.org/wiki/Graphics_Interchange_Format#Example_GIF_file
I'd like to implement this in either Perl or C/C++. Any language will do though.
Many thanks in advance,
Thanks guys for all the replies. I removed the leading '0d 0a 0d 0a'...
Here's what I have sofar:
#!/usr/bin/perl
use strict;
use warnings;
open(IN,"<test.txt");
open(OUT,">test.gif");
my #lines=<IN>;
foreach my $line (#lines){
$line=~s/\n//g;
my #bytes=split(/ /,$line);
foreach my $byte (#bytes){
print OUT $byte;
}
}
close(OUT);
close(IN);
You can do it in the shell, using GNU echo:
$ /bin/echo -n -e "\x47\x49\x46\x38\x39\x61\x01\x00\x01\x00\x80\xff\x00\xff\xff\xff\x00\x00\x00\x2c\x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02\x44\x01\x00\x3b" > foo.gif
$ identify foo.gif
foo.gif GIF 1x1 1x1+0+0 8-bit PseudoClass 2c 36B 0.000u 0:00.000
You can also use the xxd command which will "make a hexdump or do the reverse". Annoyingly, however, it seems very picky about the input format. Here's an example using xxd:
$ cat > mygif.hex <<END
0000000: 4749 4638 3961 0100 0100 80ff 00ff ffff
0000010: 0000 002c 0000 0000 0100 0100 0002 0244
0000020: 0100 3b0a
END
$ xxd -r < mygif.hex > mygif.gif
gvim has an interface to xxd. Use the "Tools → Convert To Hex" menu option (keyboard: :%!xxd) and then "Tools → Convert Back" (:%!xxd -r).
EMACS also has a built-in hex editor, which is accessed by M-x hexl-mode (see Editing Binary Files in the manual). It's also a little bit annoying, because you have to type C-M-x (i.e. Ctrl-Meta-X) before entering a character by its hex code:
Of course, it is very easy to write a simple C program to do the conversion:
#include <stdio.h>
int main(int argc, char **argv) {
unsigned int c;
while (1 == scanf("%x", &c))
putchar(c);
return 0;
}
usage:
$ gcc -Wall unhexify.c -o unhexify
$ echo "47 49 46 38 39 61 01 00 01 00 80 ff
00 ff ff ff 00 00 00 2c 00 00 00 00
01 00 01 00 00 02 02 44 01 00 3b" | ./unhexify > mygif.gif
Also: many answers here in this code golf question.
Open a new file for writing (in binary mode) with the .gif extension.
Read each pair of hex characters.
Convert the hex to a byte (char) value.
Write the byte to the opened file.
When finished, close the file.
If the hex data represents a GIF image, the file should contain it.
perl -ne'
BEGIN { binmode STDOUT }
s/\s//g;
print pack "H*", $_;
' file.hex > file.gif
Perl 5.14:
perl -ne'
BEGIN { binmode STDOUT }
print pack "H*", s/\s//gr;
' file.hex > file.gif
(-n and print can be replaced with -p and $_ = if you want to golf (shorten the length of the program.)
You may want to read the documentation for unpack (or hex) and pack. You may also find the perlio documentation useful for creating a raw file handle (so perl doesn't try to help you with things like encodings or line endings).