如何获取Bash版本号

37

我正在编写一个需要获取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

不过,如果那个消息因为任何原因略微更改,这种方法似乎容易出现故障。

有没有更好的方法来解决这个问题,如果有的话,什么是更好的方法?

8个回答

39

还有一个特殊数组(BASH_VERSINFO),其中包含每个版本号在不同元素中。

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

请参见9.1. 内部变量以获取更多信息:

# Bash version information:

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).

34

如果您正在Bash shell中运行,则应该设置$BASH_VERSION环境变量:

$ echo $BASH_VERSION
4.2.8(1)-release

这样解析应该更容易、更可靠。请参见man手册,查看shell设置的环境变量列表。


4
我发现了 $BASH_VERSINFO,通过它我可以仅使用所需的位数来构建它。但是有一点奇怪的是,我机器上的 man 页面没有提到它设定的环境变量。谢谢 :) - stwalkerster

11

要提取第一部分:

$ echo ${BASH_VERSION%%[^0-9.]*}
4.2.10

2
仅输出主版本号:echo ${BASH_VERSION%%[^0-9]*} - Brad Koch
3
回显 $BASH_VERSINFO - Pierre Prinetti

3

这个似乎有一个环境变量可以解决:

echo $BASH_VERSION

产量
4.1.7(1)-release

在我的设备上。

只是一个 shell 变量(仅在 bash 中可见),未导出到环境中。 - Wolfram Rösler

2

FelixEnescu的回答上进行改进:

通过内置的数组shell变量BASH_VERSINFO报告前三个版本号组件,例如4.2.10

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

如果您正在Bash脚本中调用此命令,请使用一个子shell来限定更改IFS的影响:

#!/usr/bin/env bash

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

说明:

  • IFS=. 将内部字段分隔符设置为 .,这样确保我们稍后在双引号字符串中打印数组时,数组的元素将与该分隔符连接。

    • 请注意,您不能仅通过 IFS=. echo ... 来瞬时重新定义仅适用于 echo 命令作用域的 IFS ,因为 shell 参数扩展 (本例中的 ${BASH_VERSINFO[*]: 0:3} 的扩展) 发生在调用 echo 之前。 因此,需要两个单独的命令; 使用命令替换($(...)) 确保对 IFS 的更改仍然是本地化的,因为命令替换运行在子shell 中。
  • ${BASH_VERSINFO[*]: 0:3} 从数组变量 $BASH_VERSINFO 中提取前3个元素(从索引 0 开始,返回 3 个元素)。

    • 请注意,为了使 IFS 起到预期的作用,必须使用 * 而不是 @ 引用数组; 不管 $IFS 的值如何,@ 都会无论如何将元素分隔为单个空格。

2

FelixEnescu 的优秀回答 上进行扩展,这里提供一个函数,检查 Bash 版本是否符合要求,可以仅检查主版本或主次版本组合,并且如果当前 Bash 版本 >= 所需版本,则返回 0:

Original Answer 翻译成 "最初的回答"

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

    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

请看与此相关的断言:

https://github.com/codeforester/base/blob/f230fbacbb1d9fe48d68ce9302902fe2d3785dde/lib/assertions.sh#L12

"Original Answer"翻译成:"最初的回答"


1

运行 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来提取版本号,以下是具体命令:
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 ~]$

0

这是其他使用 BASH_VERSINFO 的响应的变体:

check_bash_version()
{
    local a=4 b=3   # Bash version >= a.b

    (( BASH_VERSINFO[0] > a || \
      (BASH_VERSINFO[0] == a && BASH_VERSINFO[1] >= b) )) || {
        echo "Error: Bash version >= $a.$b expected." >&2
        return 1
    }
}

check_bash_version || exit 1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接