bash - 在第一个分隔符之前和之后获取字符串

bash - 在第一个分隔符之前和之后获取字符串

我有一个值为 2022.2.1 的字段版本。我需要获得价值2022.2在我的所有示例中(第一个分隔符之前和之后的字符串)。

version="2022.2.1"
echo "${version%.*}"
2022.2

这有效。但如果版本包含多个点作为分隔符(例如version="2022.2.1.1"),它将不起作用 - 我需要这里的值2022.2

或者即使版本中包含多个版本,它也不会工作(version="2022.2.1 2021.1.0")。同样,在此示例中,我只需要第一个值,并且它是第一个分隔符之前和之后的第一个字符串。所以我总是想获得价值2022.2

此用例的最佳实践是什么?谢谢!

答案1

您无法通过变量修改轻松做到这一点。在这里,我曾经cut挑选出前两个.分隔字段(man cut详情请参阅):

for version in '2022.2.1' '2022.2.1.1' '2022.1.1 2021.1.0'
do
    shorter=$(cut -d. -f1-2 <<<"$version")
    printf "version=%s => %s\n" "$version" "$shorter"
done

输出

version=2022.2.1 => 2022.2
version=2022.2.1.1 => 2022.2
version=2022.1.1 2021.1.0 => 2022.1

对于没有 POSIX shell 的情况,<<<您可以通过管道将字符串传递到cut

shorter=$(printf "%s\n" "$version" | cut -d. -f1-2)

答案2

使用普通的 bash,您可以执行以下操作:

  • 拆分和合并

    IFS=. read -ra fields <<< "$version"
    ver2=$(IFS=.; echo "${fields[*]:0:2}")
    
  • 正则表达式捕获

    [[ $version =~ ([^.]+\.[^.]+) ]] && ver2=${BASH_REMATCH[1]}
    

答案3

zsh

$ set -o extendedglob
$ print -r -- ${(M)version##[^.]#.[^.]#}
2022.2

(M)导致膨胀导致M接合的前导部分而不是剥离匹配的部分。

$ print -r -- ${(j[.])${(s[.])version}[1,2]}
2022.2

(与前 2 个结果单词分开s) 。.j.

POSIXly:

printf '%s\n' "${version%".${version#*.*.}"}"

或者:

$ LC_ALL=C expr "x$version" : 'x\([^.]*\.[^.]*\)'
2022.2

相关内容