我想从中提取版本字符串(1_4_5)my-app-1_4_5.img,然后转换为不带文件名的点版本(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。
这是参数扩展的尝试。我假设您有一个要循环的通配符模式。
for file in *-*.img; do
base=${file%.img}
ver=${base##*-}
echo "${ver//_/.}"
done
该构造返回删除任何后缀匹配${var%pattern}的变量。同样,修剪任何匹配的前缀。在这两种情况下,将运算符加倍会切换到修剪可能最长的匹配而不是最短匹配。(这些是 POSIX 兼容的 pattenr 扩展,即严格来说并非仅限 Bash。)该构造将on中的第一个匹配替换为; 将第一个斜线加倍会导致每个匹配项都被替换。(这只是 Bash。)varpattern${var#pattern}pattern${var/pattern/replacement}varpatternreplacement
你可以用sed做到这一点:
sed -E "s/.*([0-9]+)_([0-9]+)_([0-9]+).*/\1.\2.\3/" <<< 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 参考手册:3.5.1 大括号扩展。
删除除0to和换行符之外的所有内容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