Kir*_*ira 3 shell bash regular-expression
我对这个替换正则表达式有点挣扎,我不明白它为什么会这样。我想要做的是替换最后一个之后的所有数字/:
str="aa/a0b0/42"
echo ${str/%[[:digit:]]*/5}
echo ${str/%[0-9]*/5}
Run Code Online (Sandbox Code Playgroud)
两者都作为输出echo产生aa/a5。预期的输出将是aa/a0b0/5。
我很清楚我可以使用诸如sed和 之类的工具awk来解决我的问题,而且我确实知道该怎么做,但我正在寻找一种仅使用 bash 的解决方案。
我想了解为什么[0-9]*扩展到 0b0/42 而不仅仅是数字。
将%在我的正则表达式是让后端更换。
因为那是模式匹配,而不是正则表达式。
[[:digit:]]*表示一个数字后跟任何字符串,这就是0b0/42匹配的原因。它是一个数字,0,后跟一个字符串,b0/42。
现在,在bash与extglob启用,您可以用+(pattern-list)匹配一个模式的一次或多次出现:
$ shopt -s extglob
$ printf '%s\n' "${str/%+([[:digit:]])/5}"
aa/a0b0/5
Run Code Online (Sandbox Code Playgroud)
默认情况下,您在 中有该语法ksh,它bash是从 .
在 中zsh,虽然您可以使用这些ksh模式setopt kshglob或使用zsh自己的extendedglob( [[:digit:]]##),但您也可以使用regex-replace 函数执行正则表达式替换:
$ str="aa/a0b0/42"
$ autoload -U regexp-replace
$ regexp-replace str '[[:digit:]]+$' 5
$ print -rl -- $str
aa/a0b0/5
Run Code Online (Sandbox Code Playgroud)
如果您确保最后一个之后的部分/始终编号,则可以 POSIXly 进行:
printf '%s/%s\n' "${str%/*}" 5
Run Code Online (Sandbox Code Playgroud)