Reputation: 55
I'm having difficulty using variables inside a perl command.
What I'm trying to do is convert a perl command to a bash script. The bash script would be used to search any given file for a given regex pattern. The bash script should first request which file to open and then request the regex pattern.
I already have a working command line and everything I tried to convert it to a bash script didn't work... I don't have much experience with command lines and bash script and I have read a lot on the internet and nothing seems to work.
#!/bin/bash
read -p "Enter the path to the file : " file_path
read -p "Enter the regular expression : " reg_exp
perl -ln0777e 'my $count=1; print "===================== RESULTS ====================="; while (/'"${reg_exp}"'/g) {printf("[%02d] Offset: 0x%x length: %dB\n Position: %d to %d \n Hex match: %s\n Original: %s\n", $count++, $-[ 0 ], length $1, $-[ 0 ], $-[ 0 ] + length( $1 ) - 1, unpack("H*",$1), $1)}' "${file_path}"
When I try to use the variables inside the regex, it doesn't seem to be interpreted as a variable...
This is what the result should look like: enter image description here
My command line is this:
perl -ln0777e 'my $count=1; print "===================== RESULTS ====================="; while (/REGULAR_EXPRESSION/g) {printf("[%02d] Offset: 0x%x length: %dB\n Position: %d to %d \n Hex match: %s\n Original: %s\n", $count++, $-[ 0 ], length $1, $-[ 0 ], $-[ 0 ] + length( $1 ) - 1, unpack("H*",$1), $1)}' SOURCE_FILE
SOLUTION:
Here is the working code that I came up with. Thank you Ikegami for your help!
#!/bin/bash
read -rp "Enter the path to the file : " file_path
read -rp "Enter the regular expression : " reg_exp
perl -sn0777e'
while (/$reg_exp/g) {
printf "[%1\$02d] Matched %2\$d bytes from position %3\$d (0x%3\$x) to %4\$d (0x%4\$x)\n",
++$count, $+[0]-$-[0], $-[0], $+[0]-1;
printf " Hex: %s\n", unpack("H*", $&);
printf " Match: %s\n", $&;
}
' -- -reg_exp="${reg_exp}" -- "${file_path}"
Upvotes: 0
Views: 95
Reputation: 386206
The snippet attempts to generate Perl code, but it does so incorrectly. This is known as a code injection bug.
The easiest way to fix this is to avoid generating Perl code at all. This other answer suggests ways to pass data to a Perl one-liner. We'll use the second one here.
perl -sn0777e'
while (/$reg_exp/g) {
printf "[%1\$02d] Matched %2\$d bytes from position %3\$d (0x%3\$x) to %4\$d (0x%4\$x)\n",
++$count, $+[0]-$-[0], $-[0], $+[0]-1;
printf "Match: %s\n", $&;
printf "Hex: %s\n", unpack("H*", $&);
}
' -- -reg_exp="$reg_exp" -- "$file_path"
I made a few changes:
$&
and $+[0]
instead of $1
(and length($1)
).Note that you can get weird output for 0-characters matches (e.g. 0 bytes from position 6 to 5
). For this reason, an exclusive end position is often used ($+[0]
instead of $+[0]-1
). I left this unchanged since 0-character matches are unlikely and inclusive positions are often used as well.
Upvotes: 3