Я должен протестировать, если номер версии 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.
В моем сценарии удара я хотел бы вставить тест остроты в самом изящном / эффективный / читаемый способ, которым также приняты возможные, но другие подходы.
Существует пара способы приблизиться к тому, чего Вы хотите достигнуть.
Достаточно только для наблюдения то, что находится в $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
Это не острота, хотя это намного лучше. Качество по количеству.
Для этого необходимо отфильтровать вывод 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), это не принесет Вам пользы.
Одним способом обойти его является просто разрешение использование ассоциативные массивы и выход когда bash
не может использовать их. set -e
строка ниже #!/bin/bash
позволит сценарию выходить, если сценарий не может использовать ассоциативный массив.
Это потребует, чтобы Вы явно сказали пользователю: "Эй, Вы действительно должны колотить версию 4.3 или выше, иначе сценарий не будет работать". Затем ответственность лежит на пользователе, хотя некоторые могли бы утверждать, что это не действительно хороший подход к разработке программного обеспечения.
bash
сценарии не являются портативными, потому что его синтаксис не совместим с Оболочкой Bourne. Если сценарий, который Вы пишете, будет используемым на диапазоне различных систем, не только одной только Ubuntu, то откажитесь от всей надежды и найдите способы использовать что-то другое, чем ассоциативные массивы. Это могло бы включать наличие двух массивов или парсинг конфигурационного файла. Рассмотрите также переключение на другой язык, Perl или Python, где синтаксис является, по крайней мере, более портативным, чем bash
.
Я разработал сценарий, который привлекает ответы в Переполнении стека. Один из тех ответов, ведомых к Сотруднику 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
Попытка:
$ [ "${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
Вместо того, чтобы сравнить номера версий, Вы могли протестировать непосредственно на саму функцию. 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