我正在尝试仅使用bash和unix工具将此3.11.0.17.16
转换为3.11.0-17-generic
。原始字符串中的16
可以是任何内容。我觉得sed
就是答案,但我对它的正则表达式味道感到不舒服。你会怎么做?
使用 awk
而不是 sed
的版本:
echo "3.11.0.17.16" | awk -F. '{printf "%s.%s.%s-%s-genericn",$1,$2,$3,$4}'
echo "3.11.0.17.16" | sed 's/.([0-9][0-9]*).[0-9][0-9]*$/-1-generic/'
3.11.0-17-generic
这只接受最终组件中的数字。 如果要接受 . 以外的任意字符(您不能允许 . 否则匹配将变得不明确),则改为编写
echo "3.11.0.17.gr@wl1x" | sed 's/.([0-9][0-9]*).[^.][^.]*$/-1-generic/'
在可移植sed
调用中,您只能使用 POSIX 基本正则表达式,最重要的是这意味着您不能使用 +
、?
或 |
,并且除非转义,否则
(
)
{
}
都是普通字符。许多sed
实现现在接受一个-E
选项,使其正则表达式语法与egrep
保持一致,但这甚至不是POSIX最新版本的功能,因此您不能依赖它。
使用 bash 参数扩展和扩展 glob 删除子字符串
shopt -s extglob
version=3.11.0.17.16
version=${version%.+(!(.))}
printf "%s-%s-genericn" ${version%.+(!(.))} ${version##*.}
3.11.0-17-generic
如果您锚定正则表达式,您将尝试匹配到最后 3 组数字上,您将获得
echo "3.11.0.17.16" | sed 's!([0-9]*).([0-9]*).([0-9]*)$!1-2-generic!'