如何将语义版本 shell 变量转换为移位整数?

How to convert a semantic version shell variable to a shifted integer?

给定一个值为语义版本的 shell 变量,我如何创建另一个值为 (tuple 1 × 1000000) + (tuple 2 × 1000) + (元组 3) ?

例如

$ FOO=1.2.3
$ BAR=#shell magic that, given ${FOO} returns `1002003`
# Shell-native string-manipulation? sed? ...?

我不清楚 POSIX-compliance 与 shell-specific 语法在这里如何发挥作用,但我认为非 bash-specific 的解决方案是首选。


更新: 澄清一下:这不像用零替换“.”那么简单,这是我最初的想法。

例如1.12.30 的期望输出是 1012030,而不是 100120030,这是 . 替换方法可能提供的。


如果答案可以是单行变量赋值则加分。

应该这样做

echo $foo | sed 's/\./00/g'

按点拆分,然后循环 multiply/add:

version="1.12.30"

# Split on dots instead of spaces from now on
IFS="."

# Loop over each number and accumulate
int=0
for n in $version
do
  int=$((int*1000 + n))
done

echo "$version is $int"

请注意,这对 1.2 和 0.1.2 的处理方式相同。如果您想始终将第一个数字视为 major/million,请事先考虑 padding/truncating。

这个怎么样?

$ ver=1.12.30
$ foo=$(bar=($(echo $ver|sed  's/\./ /g')); expr ${bar[0]} \* 1000000 + ${bar[1]} \* 1000 + ${bar[2]})
$ echo $foo
1012030

一个 perl 单行代码:

echo $FOO | perl -pne 's/\.(\d+)/sprintf "%03d", /eg'

工作原理:

  • perl -pne 使用提供的程序
  • 执行REPL
  • 程序包含替换功能s///
    • 搜索字符串是正则表达式 \.(\d+),它匹配以点开头并以数字结尾的字符串并捕获这些数字
    • e modifier of the s/// function evaluates the right-hand side of the s/// replacement as an expression. Since we captured the digits, they'll be converted into int and formatted into leading zeros with sprintf
    • g 修饰符替换输入字符串中正则表达式的所有实例

Demo