Проверьте, ли версия Bash> = дана номер версии

Я должен протестировать, если номер версии Bash> = к определенному числу. Например, я имею:

$ bash --version
GNU bash, version 4.3.48(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2013 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.

Для использования ассоциативных массивов, номер версии удара должен быть> =4.

В моем сценарии удара я хотел бы вставить тест остроты в самом изящном / эффективный / читаемый способ, которым также приняты возможные, но другие подходы.

11
задан 5 August 2019 в 09:58

4 ответа

Существует пара способы приблизиться к тому, чего Вы хотите достигнуть.

1. Используйте $BASH_VERSION

Достаточно только для наблюдения то, что находится в $BASH_VERSION переменная. Лично я использовал бы подоболочку как так:

$ (read -d "." version trash <<< $BASH_VERSION; echo "$version" )
4

Отметьте это <<< синтаксис для здесь-документа не является портативным, если Вы собираетесь использовать его с /bin/sh, который является Тире на Ubuntu и мог бы быть чем-то еще в другой системе

Альтернативный путь через оператор выбора или если оператор. Лично, я сделал бы это:

bash-4.3$ case $BASH_VERSION in 4.*) echo "Can use associative arrays";; ?) echo "can't use associative arrays" ;; esac
Can use associative arrays

Вероятно, ради мобильности, вероятно, необходимо проверить, установлена ли такая переменная даже вообще во-первых с чем-то как [ -n $BASH_VERSION ]

Это полностью может быть переписано как функция, которая будет использоваться в сценарии. Что-то длинное строки:

#!/bin/bash
version_above_4(){
    # check if $BASH_VERSION is set at all
    [ -z $BASH_VERSION ] && return 1

    # If it's set, check the version
    case $BASH_VERSION in 
        4.*) return 0 ;;
        ?) return 1;; 
    esac
}

if version_above_4
then
    echo "Good"
else
    echo "No good"
fi

Это не острота, хотя это намного лучше. Качество по количеству.

2. Проверьте то, что установлено

Для этого необходимо отфильтровать вывод apt-cache policy как так

$ apt-cache policy bash | awk -F '[:.]' '/Installed:/{printf "%s\n",substr($2,2)}'
4

dpkg-query может также пригодиться с некоторой фильтрацией через awk.

$ dpkg-query -W bash | awk '{print substr($2,1,1)}'   
4

Обратите внимание, что это не портативно, с тех пор если существует нет dpkg или apt установленный в системе (например, RHEL или FreeBSD), это не принесет Вам пользы.

3. Используйте набор-e для выхода из сценария, если существует ошибка

Одним способом обойти его является просто разрешение использование ассоциативные массивы и выход когда bash не может использовать их. set -e строка ниже #!/bin/bash позволит сценарию выходить, если сценарий не может использовать ассоциативный массив.

Это потребует, чтобы Вы явно сказали пользователю: "Эй, Вы действительно должны колотить версию 4.3 или выше, иначе сценарий не будет работать". Затем ответственность лежит на пользователе, хотя некоторые могли бы утверждать, что это не действительно хороший подход к разработке программного обеспечения.

4. Откажитесь от всей надежды и записи портативные, совместимые POSIX сценарии

bash сценарии не являются портативными, потому что его синтаксис не совместим с Оболочкой Bourne. Если сценарий, который Вы пишете, будет используемым на диапазоне различных систем, не только одной только Ubuntu, то откажитесь от всей надежды и найдите способы использовать что-то другое, чем ассоциативные массивы. Это могло бы включать наличие двух массивов или парсинг конфигурационного файла. Рассмотрите также переключение на другой язык, Perl или Python, где синтаксис является, по крайней мере, более портативным, чем bash.

5
ответ дан 23 November 2019 в 03:52

Острота, не возможная, но сценарий удара, возможна

Я разработал сценарий, который привлекает ответы в Переполнении стека. Один из тех ответов, ведомых к Сотруднику Dell, пишущему сравнения номера версии в 2004 для приложения DKMS.

Код

Сценарий удара ниже должен быть отмечен как исполняемый файл с помощью команды chmod a+x script-name. Я использую имя /usr/local/bin/testver:

#!/bin/bash

# NAME: testver
# PATH: /usr/local/bin
# DESC: Test a program's version number >= to passed version number
# DATE: May 21, 2017. Modified August 5, 2019.

# CALL: testver Program Version

# PARM: 1. Program - validated to be a command
#       2. Version - validated to be numberic

# NOTE: Extracting version number perl one-liner found here:
#       http://stackoverflow.com/questions/16817646/extract-version-number-from-a-string

#       Comparing two version numbers code found here:
#       http://stackoverflow.com/questions/4023830/how-compare-two-strings-in-dot-separated-version-format-in-bash

# Map parameters to coder-friendly names.
Program="$1"
Version="$2"

# Program name must be a valid command.
command -v $Program >/dev/null 2>&1 || { echo "Command: $Program not found. Check spelling."; exit 99; }

# Passed version number must be valid format.
if ! [[ $Version =~ ^([0-9]+\.?)+$ ]]; then
    echo "Version number: $Version has invalid format. Aborting.";
    exit 99
fi

InstalledVersion=$( "$Program" --version | perl -pe '($_)=/([0-9]+([.][0-9]+)+)/' )
# echo "Installed Version: $InstalledVersion"

if [[ $InstalledVersion =~ ^([0-9]+\.?)+$ ]]; then
    l=(${InstalledVersion//./ })
    r=(${Version//./ })
    s=${#l[@]}
    [[ ${#r[@]} -gt ${#l[@]} ]] && s=${#r[@]}

    for i in $(seq 0 $((s - 1))); do
        # echo "Installed ${l[$i]} -gt Test ${r[$i]}?"
        [[ ${l[$i]} -gt ${r[$i]} ]] && exit 0 # Installed version > test version.
        [[ ${l[$i]} -lt ${r[$i]} ]] && exit 1 # Installed version < test version.
    done

    exit 0 # Installed version = test version.
else
    echo "Invalid version number found for command: $Program"
    exit 99
fi

echo "testver - Unreachable code has been reached!"
exit 255
2
ответ дан 23 November 2019 в 03:52

Попытка:

$ [ "${BASH_VERSINFO:-0}" -ge 4 ] && echo "bash supports associative arrays"
bash supports associative arrays

BASH_VERSINFO переменная типа массив только для чтения, участники которой держат информацию о версии для этого экземпляра удара. Так как это было начато с удара 2.0, это, вероятно, поддерживается всеми версиями удара, с которыми Вы встретитесь. Но, чтобы быть осторожными, мы включаем значение по умолчанию 0 для любого более раннего удара версии, для которого сброшена эта переменная.

информация о версии Извлечения из других программ

Вы спросили о LibreOffice, Python, ядре, и т.д.

, LibreOffice производит информацию о версии, которая похожа:

$ libreoffice --version
LibreOffice 5.2.6.2 20m0(Build:2)

Для извлечения номера версии:

$ libreoffice --version | cut -d' ' -f2
5.2.6.2

Для Python:

$ python -c 'import platform; print(platform.python_version())'
2.7.13

Для получения версии ядра используйте uname:

$ uname -r
4.9.0-2-amd64
14
ответ дан 23 November 2019 в 03:52

Вместо того, чтобы сравнить номера версий, Вы могли протестировать непосредственно на саму функцию. declare -A возвраты 2 (по крайней мере, в Bash 3.2), если это не распознает -A, таким образом протестируйте на тот (это также печатает ошибку):

unset assoc
if ! declare -A assoc ; then
    echo "associative arrays not supported!"
    exit 1
fi

(declare -A var также сбои, если var неассоциативный массив, таким образом unset это сначала.)

, В то время как я действительно не принимаю ничья попытка бэкпортировать функции в Bash, в целом более уместно проверить на функции, не версии. Даже в случае Bash, кто-то мог бы скомпилировать версию только с ограниченными функциями...

<час>

более общий случай тестирования номеров версий имеет две части: 1) как найти, что число правильной версии тестирует и 2) как сравнить его с другим значением.

первым является более трудный. Много программ говорят свой номер версии с флагом командной строки как --version или -v, но выходной формат варьируется, и программно выбор номера версии может быть трудным. Затем существует проблема возможного наличия нескольких версий той же программы, установленной одновременно.

второе зависит от некоторого знания формата номеров версий. dpkg может выдержать сравнение номера версий Debian-стиля (который я думаю, включает версии типа semver как подмножество):

if dpkg --compare-versions 4.3.30 ge 4.0.0 ; then
    echo "it's version 4.x"
fi

Или, только для объединения вышеупомянутого:

bashver=$( bash --version | sed -Ee 's/GNU bash, version ([0-9.]+).*/\1/;q' )
if dpkg --compare-versions "$bashver" ge 4.0.0 ; then
    echo "'bash' in your path is version 4.x"
fi
8
ответ дан 23 November 2019 в 03:52

Другие вопросы по тегам:

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