0

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

4
  • Use grep -oP 'all:\s*\K\d+' or even grep -oP '^all:\s*\K\d+$' Commented Jul 4, 2018 at 14:56
  • now, execution stop and in console, it shows > . I have use ctrl+c to stop it Commented Jul 4, 2018 at 15:04
  • Try awk -F": " '{if ($1 == "all") {print $2;}}' Commented Jul 4, 2018 at 15:07
  • No ...still no output ... :( Commented Jul 4, 2018 at 15:12

1 Answer 1

1

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.

Sign up to request clarification or add additional context in comments.

2 Comments

that works exactly what i want . Thanks ... but what you do by perl seems complex to me, i have to understand it ...... :)
Glad it worked for you @EricIpsum :) I've just updated the answer with information on how the Perl part works. I tried to keep it simple, without going too much into Perl details. Let me know if it is clear enough!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.