Eric Ipsum
Eric Ipsum

Reputation: 745

Fetch specific value from output using grep+regex and store in variable in shell

First seeking apology for this silly question as i am not expert at all on this.

I have get the out put from a task like below:

image4.png PNG 1656x839 1656x839+0+0 8-bit sRGB 155KB 0.040u 0:00.039
image4.png PNG 1656x839 1656x839+0+0 8-bit sRGB 155KB 0.020u 0:00.030
Image: image4.png
Channel distortion: AE
red: 0
green: 0
blue: 0
all: 0 
image4.png=>tux_difference.png PNG 1656x839 1656x839+0+0 8-bit sRGB 
137KB 0.500u 0:00.140

From here, i only want to get the value of all

For this i am trying to do this:

var="$(compare -verbose -metric ae path/actual.png path/dest.png path/tux_difference.png 2>&1 | grep 'all:\s(\d*)')"

But it does nothing.

use

"sudo apt-get install imagemagick" 

to make compare workable. recommend to use same Image for source and destination, otherwise you will get error for some image mismatch.

click here to

Upvotes: 0

Views: 117

Answers (1)

sidyll
sidyll

Reputation: 59327

You might need to escape your parenthesis (or just remove them) in:

grep 'all:\s\(\d*\)'

However grep by default will print the whole line, which is not what you want. Printing only the matched text is possible, but extracting the number from that requires a more complex regex which may or may not be available in your version of grep. GNU grep has the P flag to enable Perl like regex, and outputting the match only can be done with the o flag.

On the other hand, my recommendation is to use Perl directly:

perl -ne 'print $1 if /all: (\d+)/'

Note that you also don't need those quotes around $(). Considering your compare call is working properly and outputting the text in your question, then this should do what you asked:

var=$( compare [...] | perl -ne 'print $1 if /all: (\d+)/' )
echo $var

You can also use variations like /all:\s*(\d+)/ if the white space before the number is not guaranteed to be there.


The Perl code used here is largely based on the -n flag, which assumes the following loop around the program:

while (<>) {
    # ...
}

This loops iterates over the input line by line, and the <> already assumes input as either stdin or filenames given as arguments.

The -e flag precedes the code itself:

print $1 if /all: (\d+)/;

Which is just a shorthand for:

if (/all: (\d+)/) {
    print $1;
}

Here the match operator m// (or /<regex> for short) tests the default variable $_ to see if there is a match for the regex. Who had set the $_ variable? The loop itself in its (<>) construct. It automatically sets $_ to each line being read.

If the regex matches, we print it's first set of parenthesis (group), which has its contents set to $1. If the regex had other groups, they would be stored in $2, $3, and so forth.

Upvotes: 1

Related Questions