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

$ awk 'NF > 10 { print NR }' data.in

Это выведет номера строк (на самом деле номера записей, но поскольку строка - это запись по умолчанию, разницы нет) каждой строки, содержащей более 10 полей. Поле - это строка, по умолчанию разделенная пробелами, если у вас другой разделитель, используйте -F (-F ',' для запятых):

$ awk -F ',' 'NF > 10 { print NR }' data.in

Если вы хотите видеть строку, а не ее номер, это еще проще:

$ awk 'NF > 10' data.in
3
12.03.2016, 01:12
3 ответа

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
2
27.01.2020, 21:18
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
3
27.01.2020, 21:18

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

Это немного излишне для вашего варианта использования, но вот функция оболочки, которая сравнивает типичные строки версий. Он следует подмножеству правил сравнения версий 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
)
1
27.01.2020, 21:18

Теги

Похожие вопросы