3

我正在为需要 Flex 和 Bison 2.5 或更高版本的程序编写 BASH 安装程序脚本。

我已经得到了检查的代码flex并且bison已经安装了。

我不确定这是否在整个版本中保持不变,但这里分别是flex --version和的输出bison --version

➜  ~  flex --version
flex 2.5.35
➜  ~  bison --version
bison (GNU Bison) 2.5
Written by Robert Corbett and Richard Stallman.

Copyright (C) 2011 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

是否有“正确”的方法来检查以确保系统具有 flex 和 bison 2.5或更高版本

4

3 回答 3

2

您可以考虑使用autotools。然后你将有预定义的宏来测试flexbison的存在:

AX_PROG_FLEX(ACTION-IF-TRUE,ACTION-IF-FALSE)
AX_PROG_BISON(ACTION-IF-TRUE,ACTION-IF-FALSE)

不幸的是,您似乎无法测试给定版本。但是负责测试 bison 和 flex 存在的 m4 宏非常短,因此您可以轻松修改它们。通过查看autotools 查找给定版本的 C++ Boost library的方式,您可能会获得一些关于如何做到这一点的灵感。实际上,如果您想出一个修改以在 autotools 中包含 flex 和 bison 的版本测试,您可以考虑贡献您的解决方案 :)

通过使用自动工具,您还将获得许多其他好处。具体来说,您将使用经过高度测试和可移植的环境来构建和安装应用程序。

如果您更喜欢使用自定义 bash 安装工具,那么我会说使用--version和解析结果(例如,通过使用正则表达式)已经是一种合适的方式。大多数(如果不是全部)GNU 应用程序很久以前就支持该--version命令作为检查实际程序版本的标准方法。

于 2012-07-22T17:14:01.073 回答
2

由于 bash 不处理浮点数,因此您可以在 awk 中进行实际比较。

for cmd in flex bison; do
   [[ $("$cmd" --version) =~ ([0-9][.][0-9.]*) ]] && version="${BASH_REMATCH[1]}"
   if ! awk -v ver="$version" 'BEGIN { if (ver < 2.5) exit 1; }'; then
      printf 'ERROR: %s version 2.5 or higher required\n' "$cmd"
   fi
done

为了让它在纯 bash 中工作,需要单独比较每个数字:

req_version=(2 5)
for cmd in flex bison; do
   [[ $("$cmd" --version) =~ ([0-9][.][0-9.]*) ]] && IFS=. read -ra version <<< "${BASH_REMATCH[1]}"

   for (( i=0; i < "${#req_version[@]}"; i++)); do
      if (( "${req_version[i]}" > "${version[i]}" )); then
         printf 'ERROR: %s version 2.5 or higher required\n' "$cmd"
         exit 1
      fi
   done
done
于 2012-07-22T18:16:21.837 回答
0

如果您提取了两个版本号,则可以将它们与如下脚本进行比较:

#!/usr/bin/env perl
#
#   Compare two version numbers:
#   Exit status 0 equal; 1 if first is larger, 2 if second is larger.

use strict;
use warnings;

die "Usage: $0 ver1 ver2\n" if (scalar(@ARGV) != 2);

my @v1 = split /[._-]/, $ARGV[0];
my @v2 = split /[._-]/, $ARGV[1];
my $n1 = scalar(@v1);
my $n2 = scalar(@v2);

my $n = $n1 < $n2 ? $n1 : $n2;

my $rc = 0;

for (my $i = 0; $i < $n && $rc == 0; $i++)
{
    $rc = 1 if ($v1[$i] > $v2[$i]);
    $rc = 2 if ($v2[$i] > $v1[$i]);
}

if ($rc == 0 && $n1 != $n2)
{
    $rc = ($n1 > $n2) ? 1 : 2;
}

exit $rc;

使用示例

$ vercmp 2.3.5 2.3.5; echo $?
0
$ vercmp 2.3.35 2.3.5; echo $?
1
$ vercmp 2.5.35 2.3.5; echo $?
1
$ vercmp 2.5.35 2.6.5; echo $?
2
$

它设法处理了大量奇怪的版本号比较,但可能不是全部。您可以对其进行设计,使其与状态 (0, 1, 2) 相呼应,而不是以不同的状态退出。

CPAN还提供许多“版本”模块。

于 2012-07-22T19:29:19.183 回答