Bash shell重新处理变量,将点替换为下划线

5

我无法让它正常运作:

echo $VERSIONNUMBER

我得到的是:v0.9.3-beta

VERSIONNUMBERNAME=${VERSIONNUMBER:1}
echo $VERSIONNUMBERNAME

我得到的结果是:0.9.3-beta

VERSION=${VERSIONNUMBERNAME/./_}
echo $VERSION

目前版本号为:0_9.3-beta

我希望版本号为:0_9_3-beta

我已经搜索了很多,但是还是无法理解。

最好的方式是用一行代码去除v并将句点替换为下划线。


另一个关于相关语法的好参考是http://wiki.bash-hackers.org/syntax/pe。 - Charles Duffy
如果它是一个正则表达式,.将匹配您字符串中的每个字符,因为在正则表达式语法中它是通配符。 - Charles Duffy
这很令人困惑,但好吧 o.O - tatsu
这有什么令人困惑的呢?请意识到,“一行代码”通常并不被认为是一个好主意——为了简洁而牺牲简单性,如果你试图构建可靠的代码,那么这是错误的方向。 - Charles Duffy
1
VERSION=$( echo ${VERSIONNUMBER:1} | tr '.' '_' ) - Jack
显示剩余7条评论
2个回答

12

让我们创建您的变量:

$ VERSIONNUMBER=v0.9.3-beta
$ VERSIONNUMBERNAME=${VERSIONNUMBER:1}

该表单仅替换第一次出现的.

$ echo "${VERSIONNUMBERNAME/./_}"
0_9.3-beta

使用以下代码替换所有出现的 .:

```javascript str.replace(/\./g, newSubStr) ```
$ echo "${VERSIONNUMBERNAME//./_}"
0_9_3-beta

因为该方法避免了创建管道和子shell以及使用外部可执行文件,所以该方法非常高效。此方法还支持unicode。

文档

来自man bash

${parameter/pattern/string}

模式替换。与路径名展开一样,将扩展模式以生成一个模式。参数被扩展,匹配参数中最长的模式被替换为字符串。如果pattern以 / 开头,则将替换所有匹配项为string。通常只替换第一个匹配项。如果 pattern 以 # 开头,则它必须匹配 parameter 扩展值的开头。如果 pattern 以 % 开头,则它必须匹配 parameter 扩展值的结尾。如果 string 为空,则删除 pattern 的匹配项,可以省略跟在 pattern 后面的 /。如果启用 nocasematch shell 选项,则执行匹配时不考虑字母字符的大小写。如果 parameter 是 @ 或 *,则将替换操作逐个应用于每个位置参数,并且扩展是结果列表。如果 parameter 是带 @ 或 * 下标的数组变量,则将替换操作逐个应用于数组的每个成员,并且扩展为结果列表。 (强调添加)


@tatsu,...因为语法没有定义成允许你这样做吗?如果你想嵌套扩展,那就是一种语言特性;如果没有,那就没有。 - Charles Duffy
真的吗?我认为像 echo ${"${VERSIONNUMBER//./_}":1} 这样的东西应该可以做到。我相信将其放入一行中是可行的。 - tatsu
@tatsu,一行代码肯定可以。一个参数扩展绝对不行。PE语法要求变量名且仅限变量名位于“parameter”位置。 - Charles Duffy
1
@tatsu,“VERSIONNUMBER=v0.9.3-beta; VERSIONNUMBERNAME=${VERSIONNUMBER:1}”-- 将换行符替换为分号,这样你就得到了一行。 - Charles Duffy
1
如果我们从头开始设计一个shell语言,它可能会具备这个功能。然而,对于bash来说,主要的设计目标是保持与数年甚至几十年前的shell代码的向后兼容性。如果你想要最新的功能,请使用zsh。如果你想要与成千上万的shell脚本兼容,这些脚本是你的操作系统的一个组成部分或者可以在互联网上获取到的,请使用bash - John1024
显示剩余3条评论

9
你可以将模式替换与tr组合使用:
VERSION=$( echo ${VERSIONNUMBER:1} | tr '.' '_' ) 

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接