首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在zsh参数展开中可以使用什么样的模式?

在zsh参数展开中可以使用什么样的模式?
EN

Unix & Linux用户
提问于 2019-12-16 11:17:42
回答 1查看 4.4K关注 0票数 14

在我的zsh脚本中,我成功地使用regexp-replace nname "_{2,}" "_"将多个"_"s简化为一个“_”,但是当我尝试${nname//_{2,}/'_'} zsh时,它似乎与模式不匹配。

man zshexpn是。不清楚。它提到了全局模式,但很明显,其他POSIX 1003.2正则表达式,如${name//[^[:alnum:]]/"_"}中的正则表达式,在我的脚本中是OK的。

动机

我在寻找参数展开等价的

代码语言:javascript
复制
regexp-replace nname "[^[:alnum:]]" "_"
regexp-replace nname "_{2,}" "_"
regexp-replace nname "_+$" ""
regexp-replace nname "^_+" ""

zsh

代码语言:javascript
复制
zsh --version
zsh 5.7.1 (x86_64-apple-darwin19.0)
EN

回答 1

Unix & Linux用户

回答已采纳

发布于 2019-12-16 11:45:44

${var//pattern/replacement}正在为pattern使用zsh通配符模式,与用于文件名生成(又名全局化)的模式相同,后者是sh通配符模式的超集。语法也受到kshglobextendedglob选项的影响。${var//pattern/replacement}最初来自Korn外壳。

我建议启用extendedglob (您的~/.zshrc中的set -o extendedglob),它为您提供了最多的特性(比标准的ERE更多),而在某些情况下却牺牲了一些向后不兼容性。

您将在info zsh 'filename generation'上找到它的文档。

ERE和扩展zsh通配符之间的映射的备忘单:

标准的sh标准:

  • . -> ?
  • .* -> *
  • [...] -> [...]

zsh扩展:

  • * -> #
  • + -> ##
  • {x,y} -> (#cx,y)
  • (...|...) -> (...|...)

一些标准ERE中没有的额外功能:

  • ^pattern (否定)
  • x~y (除外)
  • <12-234>匹配十进制数范围
  • (#i)不区分大小写匹配
  • (#a2)近似匹配允许最多两个错误。
  • 更多

通配符模式是锚定在主题的开始还是结束取决于使用什么操作符。

  • 全球模式、case模式、[[ string = pattern ]]${var:#pattern}都被锚定(f*.txt将在foo.txt上匹配,而不是Xfoo.txtY)
  • ${var#pattern}${var##pattern}在一开始就锚定在
  • ${var%pattern)${var%%pattern}锚定在最后
  • ${var/pattern/repl}${var//pattern/repl}不是锚定的,但可以使用${var/#pattern} (start)或${var/%pattern} (end)来实现。

(#s)(#e)也可以作为^/$ (ERE)或\A/\z (D90/D91)的等价物。

重复操作符(###*(#cx,y)、)是否贪婪也取决于操作符(贪心于##%%///而不是D 101D 102),可以用D 103参数展开标志进行更改。

所以对于你的例子:

  • regexp-replace nname "[^[:alnum:]]" "_"${var//[^[:alnum:]]/_}
  • regexp-replace nname "_{2,}" "_"${var//_(#c2,)/_}
  • regexp-replace nname "_+$" ""${var%%_#}${var/%_#} (在这里,使用#作为*等效项,您可以使用##作为+等效项,但在这种情况下不会有任何区别)。
  • regexp-replace nname "^_+" ""${var##_#}还是${var/#_#}

在这里,您可以将它们与${${${var//[^[:alnum:]]##/_}#_}%_}结合(将非alnum序列转换为_,并删除最终的引导或尾随_)。

另一种方法可以是提取所有的alnum序列并使用_连接它们,使用此黑客:

代码语言:javascript
复制
words=()
: ${var//(#m)[[:alnum:]]##/${words[1+$#words]::=$MATCH}}
var=${(j:_:)words}

regexp-replace本身是一个自变量函数,它在循环中调用[[ $var =~ pattern ]]。请注意,因此,它不能正常工作在^锚或字界或后视运算符(如果使用rematchpcre(备选方案)

代码语言:javascript
复制
$ a='aaab'; regexp-replace a '^a' x; echo "$a"
xxxb
$ a='abab'; regexp-replace a '\'; echo $a

(在第一个示例中,^a与该循环中的aaabaababb依次匹配)。

票数 14
EN
页面原文内容由Unix & Linux提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://unix.stackexchange.com/questions/557473

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档