如何在 shell 脚本中以编程方式提取 Python 版本?



python --version作为终端中的输入,我想确认(也在 shell 编程形式的 shell 中)安装的任何 python 版本是否为 3 或更高版本。例如

Python 3.2.1

会产生True或某种形式的确认,其中python2.2p1Python 2.1.4会产生False.

我尝试通过 sed 或 grep 使用正则表达式,但无法获得。

请注意,这与某些人认为是重复的内容不同,因为我要求可以自动确认已安装 python3 或更高版本的 shell 编程代码,而不是手动检查它的方法(只需输入python --version)。

使用 python -

-version 作为终端中的输入,我想确认(也在 shell 编程形式的 shell 中)安装的任何 python 版本是否为 3 或更高版本。

如果python命令启动任何版本的 cpython,则python --version的输出(到其 stderr,而不是 stdout)将具有以下形式:

Python X.Y.Z

您可以在 shell 脚本中对其进行测试,如下所示:

if python --version 2>&1 | grep -q '^Python 3.'; then
# It's python 3 ...
else
# It's not python 3; maybe not installed
fi

请注意,您最初在问题中提供的输出表明根本没有安装 Python。 上述方法将在该事件中执行else分支。 另请注意,Python 可以使用不同的名称安装——例如,在我键入此内容的系统上,python是 Python 2.7.5,但 Python 3.4.8 可通过命令python3获得。 您可以扩展上述内容以测试 Python 3 的一些可能的替代名称,但您无法安全、可靠或高效地执行详尽的测试,以确定是否以任何名称或路径安装了 Python 3。

在 Bash 中执行此操作的最简单方法是使用sort -V.

为了解决在 bash 中比较版本字符串的问题,这里有一个简单的compare()函数,它接受两个参数 a 和 b,如果 a <= b,则返回 true。然后一些单元测试显示了它对各种 Python 版本输入的有效性:

# test.sh
compare() {
local a=$1 ; local b=$2
[ "$( (echo "$a" ; echo "$b") | sort -V | head -1)" == "$a" ]
}
test22p1() {
compare "2.2p1" "3.0.0"
assertTrue "$?"
}
test214() {
compare "2.1.4" "3.0.0"
assertTrue "$?"
}
test300() {
compare "3.0.0" "3.0.0"
assertTrue "$?"
}
test372() {
compare "3.7.2" "3.0.0"
assertFalse "$?"
}
. shunit2

输出:

▶ bash test.sh
test22p1
test214
test300
test372
Ran 4 tests.
OK

(这些单元测试当然假设安装了 shunit2。

关于函数:

它只是呼应$a然后$b在两条单独的线上,管道进入sort -V,并占据头部。如果头部等于左侧,则返回 true ;否则,如果它等于右侧,则返回 false。

在你的问题中,你提到你真的想知道是否安装了Python 3或更高版本,所以你可以修改它并改用这样的东西:

python3_installed() {
local a b
a=$(python --version 2>&1 | perl -pe 's/python *//i') ; b=3
[ "$( (echo "$a" ; echo "$b") | sort -V | head -1)" == "$b" ]
}

此函数将计算安装的 Python 的实际版本,并使用sort -V将其与"3"进行比较,除非安装了 3 或更大版本,否则返回 false。

注意在那里使用 Perl 来执行不区分大小写的正则表达式搜索和替换。(并非所有 sed 都具有不区分大小写的功能。

这样做的好处是,当你调用它时,你可以有可读的代码,比如:

if python3_installed ; then
# yes it is!
else
# ...
fi

最后,根据sort -V的文档(来自 BSD 手册;POSIX 没有指定-V选项,但大多数排序似乎都有):

`-V, --version-sort`

对版本号进行排序。 输入行被视为前缀版本后缀形式的文件名,其中后缀与正则表达式(.([A-Za-z~][A-Za-z0-9~]*)?)*匹配。这些文件按其前缀和版本进行比较(版本号中忽略前导零,请参阅下面的示例)。 如果输入字符串与模式不匹配,则使用字节比较函数对其进行比较。 所有字符串比较都在 C 语言环境中执行,区域设置环境设置将被忽略。

下面是完成这项工作的示例 awk 脚本:

echo $(python --version) | awk 'BEGIN{found="false"}/python-3/{found="true"}END{print found}'

最新更新