使用grep + regex从输出中获取特定值,并将其存储在shell中的变量中

时间:2018-07-04 14:54:01

标签: regex shell ubuntu sh

因为这个我根本不是专家,所以首先为这个愚蠢的问题道歉。

我已经完成了如下任务:

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

从这里,我只想获取 all

的值

为此,我正在尝试这样做:

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

但是它什么也没做。

使用

"sudo apt-get install imagemagick" 

使比较可行。建议对源和目标使用同一张图片,否则某些图片不匹配会出错。

click here to

1 个答案:

答案 0 :(得分:1)

您可能需要在以下位置转义括号(或仅删除括号):

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

但是,默认情况下,grep将打印整行,这不是您想要的。仅打印匹配的文本是可能的,但是要从中提取数字,则需要更复杂的正则表达式,这可能在您的grep版本中可用,也可能不可用。 GNU grep具有P标志来启用正则表达式之类的Perl,并且只有使用o标志才能输出匹配项。

另一方面,我的建议是直接使用Perl:

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

请注意,您也不需要$()周围的引号。考虑到您的compare呼叫正常工作并输出了问题中的文本,那么这应该按照您的要求进行:

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

如果数字前的空白不能保证存在,还可以使用/all:\s*(\d+)/之类的变体。


此处使用的Perl代码主要基于-n标志,该标志假定程序周围存在以下循环:

while (<>) {
    # ...
}

此循环逐行遍历输入,并且<>已假定输入为标准输入或作为参数指定的文件名。

-e标志位于代码本身之前:

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

这只是以下内容的简写:

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

此处,匹配运算符m//(或简称为/<regex>)测试默认变量$_,以查看正则表达式是否匹配。谁设置了$_变量?循环本身在其(<>)构造中。它会自动为正在读取的每一行设置$_

如果正则表达式匹配,我们将打印它的第一组括号(组),其内容设置为$1。如果正则表达式具有其他组,则它们将存储在$2$3等中。