Bash: преобразовать строку (номер версии) в целое число

Я хочу получить версию glibc и использовать ее в выражении if, заявив, что если glibc меньше 2,15, то.

Однако проблема заключается в том, что при использовании ldd -version это выводится как строка. Мне нужно преобразовать его в целое число, чтобы сделать меньше, чем сравнение.

Раньше я делал это так

if [ "$(ldd --version | sed -n '1 p' | tr -cd '[:digit:]' | tail -c 3)" -lt 215 ]; then 

Это не очень хорошо, поскольку я должен удалить десятичную точку и не могу дать истинное сравнение номеров версий. Другая проблема заключается в том, что некоторые версии glibc имеют несколько десятичных точек (см. Здесь https://en.wikipedia.org/wiki/GNU_C_Library#Version_history ), что означало бы, что мое существующее сравнение испортится.

Поэтому для этого мне нужно будет иметь возможность конвертировать версию glibc в целое и целовать и правильно сравнивать номера версий даже с несколькими десятичными точками.

Есть идеи? благодаря

 ldd --version | sed 's/.* //;q' | awk -F. '{ if ($1 > 2 || ($1 == 2 && $2 >= 15)) { exit 0 } else {exit 1} }' 

Объяснение:

Команда sed выводит первую строку вывода из ldd --version , вырезает все до и включая последнее пространство, а затем завершает работу (поэтому она только печатает номер).

Флаг -F для наборов awk . как разделитель полей.

Если первое число (перед точкой) больше 2 или первое число равно 2, а второе число не менее 15, статус выхода awk будет «истинным». В противном случае это будет неверно.

Вы можете использовать это в сценарии bash следующим образом:

 if ldd --version | sed 's/.* //;q' | awk -F. '{ if ($1 > 2 || ($1 == 2 && $2 >= 15)) { exit 0 } else {exit 1} }' ; then echo "Version is 2.15 or later" else echo "Version is too old." fi 

Не конвертируйте строку версии в целое число. Сравните строки.

Это немного избыточно для вашего варианта использования, но вот функция оболочки, которая сравнивает типичные строки строк. Он следует подмножеством правил сравнения версий Debian :

  • Версии сравниваются куском по куску. Каждый кусок состоит из максимальной последовательности символов, которые либо полностью состоят из цифр, либо не содержат цифр.
  • Нецифровые последовательности сравниваются в лексикографическом порядке.
  • Последовательность цифр сравнивается в соответствии с десятичным значением. В частности, ведущие нули не имеют значения.

Заметим, что последняя точка: 1.01 считается равной 1.1 . Это цена за 1.1 и 1.9 которые считаются менее 1.10 .

Этот код требует тире, bash, ksh или zsh. Чтобы использовать его с другими оболочками, такими как BusyBox sh, замените вызовы на [ " STRING1 " \> " STRING2 " ] помощью expr "a STRING1 " \> "a STRING2 " .

 version_ge () ( version1="$1" version2="$2" while true; do prefix1="${version1%%[0-9]*}" prefix2="${version2%%[0-9]*}" if [ "$prefix1" \> "$prefix2" ]; then return 0; fi if [ "$prefix2" \> "$prefix1" ]; then return 1; fi version1="${version1#"$prefix1"}" version2="${version2#"$prefix2"}" prefix1="${version1%%[!0-9]*}" prefix2="${version2%%[!0-9]*}" version1="${version1#"$prefix1"}" version2="${version2#"$prefix2"}" case "$prefix2" in 0*[!0]*) prefix2="${prefix2##"${prefix2%%[!0]*}"}";; *[!0]*) :;; *) return 0;; esac case "$prefix1" in 0*[!0]*) prefix1="${prefix1##"${prefix1%%[!0]*}"}";; *[!0]*) :;; *) return 1;; esac if [ "${#prefix1}" -gt "${#prefix2}" ]; then return 0; fi if [ "${#prefix1}" -lt "${#prefix2}" ]; then return 1; fi if [ "$prefix1" \> "$prefix2" ]; then return 0; fi if [ "$prefix2" \> "$prefix1" ]; then return 1; fi done ) 

sort может сортировать номера версий; что вы можете написать что-то вроде этого:

 if [ $(printf '%s\n2.15\n' $(ldd --version | sed -n '1s/.* //p') | sort -V | head -n 1) != 2.15 ]; then # ... fi 

printf '%s\n2.15\n' $(ldd --version | sed -n '1s/.* //p') печатает номер версии ldd и 2.15 на двух отдельных строках, sort -V сортирует их в по возрастанию, а head -n 1 печатает первую строку; замена внешней команды заменяется на выход, а выход сравнивается с 2.15 ; если выход не равен 2.15 , выполняется тело if .

Пример вывода на моем компьютере с ldd 2.21 :

 % [ $(printf '%s\n2.15\n' $(ldd --version | sed -n '1s/.* //p') | sort -V | head -n 1) != 2.15 ] && printf 'Version %s is lower than 2.15\n' $(ldd --version | sed -n '1s/.* //p') || printf 'Version %s is equal or higher than 2.15\n' $(ldd --version | sed -n '1s/.* //p') Version 2.21 is equal or higher than 2.15 

Пример вывода на некоторые жестко закодированные значения, просто для демонстрации метода имеет дело со сложностью сортировки версий:

 % glibc_version=2.15 % [ $(printf '%s\n2.15\n' $glibc_version | sort -V | head -n 1) != 2.15 ] && printf 'Version %s is lower than 2.15\n' $glibc_version || printf 'Version %s is equal or higher than 2.15\n' $glibc_version Version 2.15 is equal or higher than 2.15 % glibc_version=2.16 % [ $(printf '%s\n2.15\n' $glibc_version | sort -V | head -n 1) != 2.15 ] && printf 'Version %s is lower than 2.15\n' $glibc_version || printf 'Version %s is equal or higher than 2.15\n' $glibc_version Version 2.16 is equal or higher than 2.15 % glibc_version=2.15.1 [ $(printf '%s\n2.15\n' $glibc_version | sort -V | head -n 1) != 2.15 ] && printf 'Version %s is lower than 2.15\n' $glibc_version || printf 'Version %s is equal or higher than 2.15\n' $glibc_version Version 2.15.1 is equal or higher than 2.15 % glibc_version=2.14 % [ $(printf '%s\n2.15\n' $glibc_version | sort -V | head -n 1) != 2.15 ] && printf 'Version %s is lower than 2.15\n' $glibc_version || printf 'Version %s is equal or higher than 2.15\n' $glibc_version Version 2.14 is lower than 2.15