Получить конкретное значение из вывода, используя grep + regex и сохранить в переменной в оболочке - PullRequest
0 голосов
/ 04 июля 2018

Сначала извиняюсь за этот глупый вопрос, так как я совсем не эксперт в этом.

Я получил результат от задачи, как показано ниже:

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

Отсюда я только хочу получить значение все

Для этого я пытаюсь сделать это:

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 голосов
/ 04 июля 2018

Вам может потребоваться убрать скобки (или просто удалить их) в:

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 и т. Д.

...