简体   繁体   中英

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.

点击这里

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM