bash 正则表达式匹配语义版本号

Posted

技术标签:

【中文标题】bash 正则表达式匹配语义版本号【英文标题】:bash regex to match semantic version number 【发布时间】:2014-08-10 17:15:36 【问题描述】:

我有以下几点:

versionNumber=$(sw_vers -productVersion) # Finds version number

versionShort=$versionNumber:0:4  # Cut string to 1 decimal place for calculation

当版本如下时有效:

10.9.2
10.9.5

但它不会匹配

10.10.3

因为它只会返回

10.1

但我希望将 versionShort 设置为

10.10

我想匹配上面的主要版本,第一个点和次要版本。

【问题讨论】:

【参考方案1】:

无正则表达式解决方案 - 切断最后一个点及其后面的任何内容:

versionShort=$versionNumber%.*

【讨论】:

【参考方案2】:

正则表达式解决方案:

[[ $versionNumber =~ ^[0-9]+\.[0-9]+ ]] && echo "$BASH_REMATCH[0]"

它总是会打印前两个数字,例如所有这些:

10.5
10.5.9
10.5.8.2

将导致10.5 输出。您还可以添加一个else 子句来检查是否发生了错误(未找到匹配项)。

这是一个更长的版本:

if [[ $versionNumber =~ ^[0-9]+\.[0-9]+ ]]; then
    versionShort=$BASH_REMATCH[0]
else
    echo "Something is wrong with your version" >&2
fi

【讨论】:

如何将结果返回给变量? @lukemh 我添加了一个更长的版本,可能对你来说更清楚。如果它不起作用...您确定您使用的是 bash 吗?如果是,那么是哪个版本?在版本 3 中,您必须将条件表达式的右侧放入变量中。 semantic version 标签必须正好有 3 个数字。 @MikeSamuel 是的,没错。随意编辑答案。我希望完全删除它更容易,但提及BASH_REMATCH 是一个值得的目标,即使是这样的错误答案。 ……或者你自己写,我会删除我的:)【参考方案3】:

我有一个类似的问题,但我需要访问所有 3 个部分。我做了一些研究和测试,发现这个效果很好

product_version=$(sw_vers -productVersion)
semver=( $product_version//./  )
major="$semver[0]"
minor="$semver[1]"
patch="$semver[2]"
echo "$major.$minor.$patch"

要直接回答这个问题,你可以

product_version=$(sw_vers -productVersion)
semver=( $product_version//./  )
major="$semver[0]"
minor="$semver[1]"
patch="$semver[2]"
versionShort="$major.$minor"

或者你可以使用更少的变量

product_version=$(sw_vers -productVersion)
semver=( $product_version//./  )
versionShort="$semver[0].$semver[1]"

【讨论】:

“semver=( $product_version//./ )”如何工作?不幸的是,当我尝试这个时,我得到了 semver="10.11.6//./"。 @JasonHarrison 代码通过替换点“。”来工作。用空格“”,然后将所有参数作为 bash 数组。为了使其工作,您需要首先将 semver 文本分配给一个变量。例如,a="10.11.6"; semver=( $a//./ )【参考方案4】:

https://github.com/fsaintjacques/semver-tool https://github.com/fsaintjacques/semver-tool/blob/master/src/semver

SEMVER_REGEX="^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(\\-[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?(\\+[0-9A-Za-z-]+(\\.[0-9A-Za-z-]+)*)?$"


function validate-version 
  local version=$1
  if [[ "$version" =~ $SEMVER_REGEX ]]; then
    # if a second argument is passed, store the result in var named by $2
    if [ "$#" -eq "2" ]; then
      local major=$BASH_REMATCH[1]
      local minor=$BASH_REMATCH[2]
      local patch=$BASH_REMATCH[3]
      local prere=$BASH_REMATCH[4]
      local build=$BASH_REMATCH[5]
      eval "$2=(\"$major\" \"$minor\" \"$patch\" \"$prere\" \"$build\")"
    else
      echo "$version"
    fi
  else
    error "version $version does not match the semver scheme 'X.Y.Z(-PRERELEASE)(+BUILD)'. See help for more information."
  fi

【讨论】:

注意:这个 sn-p 包含根据 GNU GPL v3 许可的代码:github.com/fsaintjacques/semver-tool/blob/master/LICENSE

以上是关于bash 正则表达式匹配语义版本号的主要内容,如果未能解决你的问题,请参考以下文章

spring cloud: zuul: 正则表达式匹配其他微服务(给其他微服务加版本号)

求一个版本号的正则表达式,版本号的格式可以是1.1或1.1.2或10000这个样子的

bash 中的正则表达式量词——简单与扩展匹配 n 次

正则表达式如何匹配+号?

正则表达式:正向反向预查

bash 正则表达式进阶--egrep