我在这个替换正则表达式上遇到了一些困难,我无法理解为什么它会这样。我想要做的是替换最后一个之后的所有数字/
:
str="aa/a0b0/42"
echo ${str/%[[:digit:]]*/5}
echo ${str/%[0-9]*/5}
两者都作为输出echo
产生。aa/a5
预期输出为aa/a0b0/5
.
我很清楚我可以使用sed
和等工具awk
来解决我的问题,并且我确实知道如何做到这一点,但我正在寻找仅 bash 的解决方案。
我想了解为什么[0-9]*
扩展为 0b0/42 而不仅仅是数字。
我的正则表达式中的内容%
是后端更换。
答案1
因为那是一个模式匹配,不是正则表达式。
[[:digit:]]*
表示一位数字后跟任何字符串,这就是0b0/42
匹配的原因。它是一位数字,0
,后跟一个字符串,b0/42
。
现在,在 中bash
,extglob
启用后,您可以使用 来+(pattern-list)
匹配模式的一次或多次出现:
$ shopt -s extglob
$ printf '%s\n' "${str/%+([[:digit:]])/5}"
aa/a0b0/5
默认情况下,您在 中具有该语法ksh
,该语法是bash
从 复制的。
在 中zsh
,虽然您可以将这些ksh
模式与setopt kshglob
或使用zsh
自己的extendedglob
( [[:digit:]]##
),但您也可以使用以下命令执行正则表达式替换正则表达式替换 功能:
$ str="aa/a0b0/42"
$ autoload -U regexp-replace
$ regexp-replace str '[[:digit:]]+$' 5
$ print -rl -- $str
aa/a0b0/5
如果你确保最后一个后面的部分/
总是数字,你可以用 POSIXly 来做到这一点:
printf '%s/%s\n' "${str%/*}" 5