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

16

我有以下内容:

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

我想要匹配上述内容中的主版本号、第一个点和次版本号。

4个回答

15

无需正则表达式的解决方案 - 去掉最后一个点及其后面的所有内容:

versionShort=${versionNumber%.*}

注意,当使用带有预发布后缀的semver版本(例如10.9.5-rc.1)时,此方法无法正常工作。 - Chris

15

正则表达式解决方案:

[[ $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
@lukemh 我添加了一个更长的版本,可能更清晰。如果它不起作用... 你确定你在使用bash吗?如果是的话,那么是哪个版本?在版本3中,您必须将条件表达式的右侧放入变量中。 - Aleks-Daniel Jakimenko-A.
1
语义化版本 标签必须恰好包含3个数字。 - Mike Samuel
@MikeSamuel 是的,没错。随意编辑回答。我希望能更容易地完全删除它,但即使像这样回答不好,提到BASH_REMATCH也是一个值得追求的目标。 - Aleks-Daniel Jakimenko-A.
…或者您可以编写自己的翻译,我会删除我的 :) - Aleks-Daniel Jakimenko-A.

13

我有一个类似的问题,但我需要访问所有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]}"

1
"semver=( ${product_version//./ } )" 这段代码是如何工作的?当我尝试时,不幸的是我得到了 semver="10.11.6//./"。 - Jason Harrison
2
@JasonHarrison 这段代码的作用是将点号“.”替换为空格“ ”,然后将所有参数作为bash数组。为了使其正常工作,您需要首先将semver文本赋值给一个变量。例如,a="10.11.6"; semver=( ${a//./ } ) - VasiliNovikov

9

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
}


5
注意:这段代码受 GNU GPL v3 许可证保护: https://github.com/fsaintjacques/semver-tool/blob/master/LICENSE - ItalyPaleAle

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