bash 提取版本字符串并转换为版本点

bash extract version string & convert to version dot

我想从 my-app-1_4_5.img 中提取版本字符串 (1_4_5),然后转换为没有文件名的点版本 (1.4.5)。版本字符串将包含三个 (1_4_5) 或四个 (1_4_5_7) 段。

让这一个班轮正常工作ls my-app-1_4_5.img | cut -d'-' -f 3 | cut -d'.' -f 1 | tr _ .

想知道是否有比管道输出更好的方法 cut

你可以用 sed:

sed -E "s/.*([0-9]+)_([0-9]+)_([0-9]+).*/../" <<< my-app-1_4_5.img

假设版本号总是在最后一个破折号和文件扩展名之间,你可以在纯 Bash:

中使用类似这样的东西
name="file-name-x-1_2_3_4_5.ext"
version=${name##*-}
version=${version%%.ext}
version=${version//_/.}
echo $version

上面的代码将导致:

1.2.3.4.5

有关上面使用的大括号扩展的完整解释,请查看 Bash Reference Manual: 3.5.1 Brace Expansion

这是参数扩展的尝试。我假设您有一个想要循环的通配符模式。

for file in *-*.img; do
    base=${file%.img}
    ver=${base##*-}
    echo "${ver//_/.}"
done

构造 ${var%pattern} returns 变量 var 与任何后缀匹配 pattern 修剪掉。类似地,${var#pattern} 删除任何匹配 pattern 的前缀。在这两种情况下,将运算符加倍会切换到修剪最长的可能匹配项而不是最短的匹配项。 (这些是 POSIX-compatible pattenr 扩展,即严格来说不仅仅是 Bash。)构造 ${var/pattern/replacement}patternvar 中的第一个匹配替换为 replacement;将第一个斜杠加倍会导致替换每个匹配项。 (这只是 Bash。)

删除除 0 以外的所有内容到 9_ 和换行符,然后将所有 _ 替换为 .:

echo "my-app-1_4_5.img" | tr -cd '0-9_\n' | tr '_' '.'

输出:

1.4.5

使用 bash 和一个正则表达式:

echo "my-app-1_4_5.img" | while IFS= read -r line; do [[ "$line" =~ [^0-9]([0-9_]+)[^0-9] ]] && echo "${BASH_REMATCH[1]//_/.}"; done

输出:

1.4.5

稍短的变体

name=my-app-1_4_5.img
vers=${name//[!0-9_]}
$ echo ${vers//_/.}
1.4.5