LINUX.ORG.RU

Выделение числа из строки в выводе команды (Bash)

 , ,


1

1

Приветствую всех. Имеется следующий скрипт:

#!/bin/sh
WAYSCAN=/usr/bin/wayland-scanner
WAYLAND_PROTOS=/usr/share/wayland-protocols
OUTPUT=gfx/common/wayland

if [ ! -d $WAYLAND_PROTOS ]; then
    WAYSCAN=/usr/local/bin/wayland-scanner
    WAYLAND_PROTOS=/usr/local/share/wayland-protocols
fi

if [ ! -d $OUTPUT ]; then
    mkdir $OUTPUT
fi

В переменной WAYSCAN хранится путь к утилите wayland-scanner. Необходимо получить версию этой утилиты и поместить её в другую переменную, однако вывод wayland-scanner --version выводит строку wayland-scanner 1.16.0. Мне нужно из этой строки выделить только число. Знаю что это можно сделать с помощью регулярки, но как не пытался - не получается. Может кто подсказать решение, пожалуйста? Только чтобы работало как в Linux, так и BSD

Ответ на: комментарий от Yorween

Сделал так, однако получаю на выходе Illegal Number, а условие со сравнением версий отрабатывается некорректно (переменной CODEGEN всегда присвается значение «private-code»). Где ошибка?

#!/bin/sh
WAYSCAN=/usr/bin/wayland-scanner
WAYSCAN_VER=$($WAYSCAN --version 2>&1 | awk '{print $2}')
WAYLAND_PROTOS=/usr/share/wayland-protocols
OUTPUT=gfx/common/wayland

if [ ! -d $WAYLAND_PROTOS ]; then
    WAYSCAN=/usr/local/bin/wayland-scanner
    WAYLAND_PROTOS=/usr/local/share/wayland-protocols
fi

if [ ! -d $OUTPUT ]; then
    mkdir $OUTPUT
fi

#Since Wayland 1.15 option "code" is deprecated. Recommended to use "private-code" option instead.
if [ "$WAYSCAN_VER -ge 1.15" ]; then
    CODEGEN=private-code
else
    CODEGEN=code
fi

Sunderland93 ★★★★★ ()
Ответ на: комментарий от Sunderland93

Про illegal number не понял, а по поводу сравнения версий, да, это так не работает.

CHECK="1.17"
if [ "$(printf '%s\n' "$WAYSCAN_VER" "$CHECK" | sort -V | tail -1)" == "$WAYSCAN_VER" ]; then
    CODEGEN=private-code
else
    CODEGEN=code
fi

+ CHECK=1.17
++ printf '%s\n' 1.16.0 1.17
++ sort -V
++ tail -1
+ '[' 1.17 == 1.16.0 ']'
+ CODEGEN=code

CHECK="1.15"
if [ "$(printf '%s\n' "$WAYSCAN_VER" "$CHECK" | sort -V | tail -1)" == "$WAYSCAN_VER" ]; then
    CODEGEN=private-code
else
    CODEGEN=code
fi

+ CHECK=1.15
++ printf '%s\n' 1.16.0 1.15
++ sort -V
++ tail -1
+ '[' 1.16.0 == 1.16.0 ']'
+ CODEGEN=private-code

Yorween ()
Ответ на: комментарий от Sunderland93

Там соль в сортировке

-V, --version-sort
              natural sort of (version) numbers within text

Выводим сравниваемые версии в формате одна версия на одну строку. Потом с помощью sort -V распределяем их в образовавшейся колонке от меньшей версии к большей. tail'ом берем значение большей. Дальше сравниваем с полученной реальной версией wayland-scan. Если она равна самой большой версии, значит версия wayland-scan или той же версии, что и значение CHECK, т.е. 1.15, или выше. А если самая большая версия после tail не совпадает с версией wayland-scan, значит версия wayland-scan меньше.

Yorween ()

Взгруснулось. Аж на комментарии хватило энтузиазма.

#!/usr/bin/env bash

# compare version from $1 and $2
# parse the format "(programm_name[- ])?[[:num:]+](\.[[:num:]]+)*(-suffix)?"
# ignore comparing a programm name and a suffix
# returns: 0 - $1=$2, 1 - $1>$2, 2 - $1<$2,
# 3 - $1 format error, 4 - $2 format error
#
# Copyright (c) 2019 may safely be consumed by a BSD or GPL license.
# Written by:   Vladimir Oleynik <dzo@simtreas.ru>

vercmp() {
	local -a va1 va2
	local ps='^(..*[- ])?([0-9][0-9]*(.[0-9][0-9]*)*)(-..*)?$' IFS=.

	# test the format and remove if present programm_name[- ] and -suffix
	[[ $1 =~ $ps ]] || return 3
	# set array=(ver_major ver_minor ver_patch...)
	va1=(${BASH_REMATCH[2]})
	# for $2 too
	[[ $2 =~ $ps ]] || return 4
	va2=(${BASH_REMATCH[2]})

	local -i i=0 c1 c2
	while [[ "${va1[i]}${va2[i]}" ]]; do
		# Removing leading zeroes, set empty as 0
		c1=$((10#${va1[i]}))
		c2=$((10#${va2[i]}))
		# compare a version item
		[[ c1 -lt c2 ]] && return 2
		[[ c1 -ne c2 ]] && return 1
		i=i+1
	done
	return 0
}


# testing
tests() {
	vercmp "$1" "$2"
	echo "'$1' <=> '$2' $? returned"
}

tests 1 0
tests 0 1
tests 1 1
tests 1.1 0
tests 0 1.1
tests 1 1.1
tests 1.1 1.1
tests 1.1 1
tests 1.2
tests a-1.3 b-1.3-suff
tests a-1.3 a-1.25
tests "b0 "
tests "c0 1" "c0 0.1"
tests 1.2.8-suff 1.2.010-suff
tests "p 1" "x 1.0"
tests "p 1." "x 1.0"
tests "p.1." "x.1.0"
tests "p.1" "x.1.0"
UPD: а $((10#...)) местный парсер не понимает...

vodz ★★★★ ()
Последнее исправление: vodz (всего исправлений: 2)