Как получить номер версии Bash

Я пишу сценарий, который требует номер версии bash в простом коротком формате.

Я знаю bash --version , но это дает длинный вывод:

GNU bash, version 4.2.10(1)-release (i686-pc-linux-gnu)
Copyright (C) 2011 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.2.10 следующим образом:

bash --version | grep "bash" | cut -f 4 -d " " | cut -d "-" -f 1  | cut -d "(" -f 1

Тем не менее, похоже, что оно может сломаться, если это сообщение когда-либо немного изменится по какой-либо причине.

Есть ли лучший способ сделать это, и что это лучше?

25
задан codeforester 20 May 2019 в 06:11
поделиться

7 ответов

Если вы работаете в оболочке bash, тогда должна быть установлена ​​переменная окружения $BASH_VERSION:

$ echo $BASH_VERSION
4.2.8(1)-release

Это должно быть проще и надежнее для анализа. См. Справочную страницу для получения списка переменных среды, установленных оболочкой.

29
ответ дан 28 November 2019 в 18:13
поделиться

Существует также специальный массив (BASH_VERSINFO), содержащий каждый номер версии в отдельных элементах.

if ((BASH_VERSINFO[0] < 3))
then 
  echo "Sorry, you need at least bash-3.0 to run this script." 
  exit 1 
fi

См. http://www.tldp.org/LDP/abs/html/internalvariables.html для получения дополнительной информации:

# Bash version info:

for n in 0 1 2 3 4 5
do
  echo "BASH_VERSINFO[$n] = ${BASH_VERSINFO[$n]}"
done  

# BASH_VERSINFO[0] = 3                      # Major version no.
# BASH_VERSINFO[1] = 00                     # Minor version no.
# BASH_VERSINFO[2] = 14                     # Patch level.
# BASH_VERSINFO[3] = 1                      # Build version.
# BASH_VERSINFO[4] = release                # Release status.
# BASH_VERSINFO[5] = i386-redhat-linux-gnu  # Architecture
                                            # (same as $MACHTYPE).
23
ответ дан 28 November 2019 в 18:13
поделиться

Извлечь первую часть:

$ echo ${BASH_VERSION%%[^0-9.]*}
4.2.10
10
ответ дан 28 November 2019 в 18:13
поделиться

Кажется, для этого есть переменная окружения:

echo $BASH_VERSION

приводит к

4.1.7(1)-release

на моей машине.

3
ответ дан 28 November 2019 в 18:13
поделиться

запустить bash --version, затем его выводу нравится

GNU bash, version 3.2.25(1)-release (x86_64-redhat-linux-gnu)

или

GNU bash, version 4.1.2(1)-release (x86_64-redhat-linux-gnu)

или

GNU bash, version 4.3.30(1)-release (x86_64-pc-linux-gnu)
<час>

используйте переменную bash $BASH_VERSION, запустите echo $BASH_VERSION, ей нравится:

4.3.30(1)-release

Обычно Я использую команду sed для извлечения версии no ., следующая конкретная команда:

bash --version | sed -r -n 's@.*version (.*)\(1\)-release.*@\1@p'

Например:

[flying@lempstacker ~]$ bash --version | sed -r -n 's@.*version (.*)\(1\)-release.*@\1@p'
4.2.46
[flying@lempstacker ~]$ 

echo $BASH_VERSION | sed -r -n 's@(.*)\(1\)-release.*@\1@p'

Например:

[flying@lempstacker ~]$ echo $BASH_VERSION | sed -r -n 's@(.*)\(1\)-release.*@\1@p'
4.2.46
[flying@lempstacker ~]$ 
1
ответ дан 28 November 2019 в 18:13
поделиться

Опираясь на полезный ответ bluecat :

Чтобы сообщить о первых 3 компонентах с номерами версий - например, 4.2.10 - через встроенную переменную оболочки BASH_VERSINFO :

$ bash -c 'IFS=.; echo "${BASH_VERSINFO[*]: 0:3}"'
4.2.10

Если вы вызываете это из скрипта Bash, используйте подоболочку , чтобы локализовать эффект изменения IFS:

#!/usr/bin/env bash

ver=$(IFS=.; echo "${BASH_VERSINFO[*]: 0:3}")  # -> e.g., $ver == '4.2.10'

Объяснение:

  • IFS=. устанавливает внутренний разделитель полей на ., что гарантирует, что при печати массива внутри двойного через строку в кавычках элементы массива объединяются с этим разделителем.

    • Обратите внимание, что вы не можете просто сделать IFS=. echo ... для временного переопределения IFS, относящегося к команде echo, потому что расширение параметра оболочки (расширение ${BASH_VERSINFO[*]: 0:3}, в этом case) происходит до вызова echo. Следовательно, необходимы две отдельные команды; использование подстановки команд ($(...)) гарантирует, что изменение в IFS все еще локализовано, потому что подстановки команд выполняются в подоболочках.
  • ${BASH_VERSINFO[*]: 0:3} извлекает первые 3 элемента из переменной массива $BASH_VERSINFO (начиная с индекса 0, возвращая 3 элементов).

    • Обратите внимание, что для того, чтобы IFS работал как предполагалось, * вместо @ должно использоваться для ссылки на массив; @ будет неизменно разделять элементы одним пробелом, независимо от значения $IFS.
0
ответ дан 28 November 2019 в 18:13
поделиться

Основываясь на великолепном ответе Bluecat , вот функция, которая проверяет только основную версию или комбинацию основной и вспомогательной версий и возвращает 0, если текущая версия bash> = = необходимая версия:

check_bash_version() {
    local major=${1:-4}
    local minor=$2
    local rc=0
    local num_re='^[0-9]+ 

Он может быть вызван как:

check_bash_version 4   # check if 4.0 or above
check_bash_version 4 2 # check if 4.2 or above
if [[ ! $major =~ $num_re ]] || [[ $minor && ! $minor =~ $num_re ]]; then printf '%s\n' "ERROR: version numbers should be numeric" return 1 fi if [[ $minor ]]; then local bv=${BASH_VERSINFO[0]}${BASH_VERSINFO[1]} local vstring=$major.$minor local vnum=$major$minor else local bv=${BASH_VERSINFO[0]} local vstring=$major local vnum=$major fi ((bv < vnum)) && { printf '%s\n' "ERROR: Need Bash version $vstring or above, your version is ${BASH_VERSINFO[0]}.${BASH_VERSINFO[1]}" rc=1 } return $rc }

Он может быть вызван как:

check_bash_version 4   # check if 4.0 or above
check_bash_version 4 2 # check if 4.2 or above
1
ответ дан 28 November 2019 в 18:13
поделиться