Regular-Expression

我可以在 zsh 參數擴展中使用什麼樣的模式?

  • December 16, 2019

在我的 zsh shell 腳本中,我regexp-replace nname "_{2,}" "_"成功地使用將多個“_”減少為一個,但是當我嘗試${nname//_{2,}/'_'}zsh 時似乎與模式不匹配。

man zshexpn是。不清楚。它提到了 globbing 模式,但顯然還有其他 POSIX 1003.2 正則表達式,例如${name//[^[:alnum:]]/"_"} 我的腳本中的 in work OK。

動機

我正在尋找參數擴展等價於

regexp-replace nname "[^[:alnum:]]" "_"
regexp-replace nname "_{2,}" "_"
regexp-replace nname "_+$" ""
regexp-replace nname "^_+" ""

zsh

zsh --version
zsh 5.7.1 (x86_64-apple-darwin19.0)

${var//pattern/replacement}正在使用 zsh 萬用字元模式,與用於文件名生成pattern的萬用字元模式相同,也就是萬用字元模式的超集。語法也受and選項的影響。最初來自Korn shell。sh``kshglob``extendedglob``${var//pattern/replacement}

我建議啟用extendedglobset -o extendedglob在您的~/.zshrc)中,它可以為您提供最多的功能(比標準 ERE 更多),但會在某些極端情況下以某些向後不兼容為代價。

您會發現它記錄在info zsh 'filename generation'.

ERE 和擴展 zsh 萬用字元之間映射的備忘單:

標準sh的:

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

zsh 擴展:

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

標準 ERE 中沒有的一些額外功能:

  • ^pattern(否定)
  • x~y(除了)
  • <12-234>匹配十進制數字範圍
  • (#i)不區分大小寫的匹配
  • (#a2)近似匹配允許最多 2 個錯誤。
  • 還有很多

萬用字元模式是錨定在主題的開頭還是結尾取決於使用的​​運算符。

  • 球體、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(PCRE) 的等價物。

重複運算符 ( #, ##, *, (#cx,y), <x-y>) 是否貪心也取決於運算符(貪心與##, %%, //,/而不是#, %),可以通過S參數擴展標誌進行更改。

所以對於你的例子:

  • regexp-replace nname "[^[:alnum:]]" "_":${var//[^[:alnum:]]/_}
  • regexp-replace nname "_{2,}" "_":${var//_(#c2,)/_}
  • regexp-replace nname "_+$" "":${var%%_#}${var/%_#}(這裡使用#等價*物,您可以使用##等價物,+但在這種情況下不會有任何區別)。
  • regexp-replace nname "^_+" ""${var##_#}${var/#_#}

在這裡,您可以將它們與${${${var//[^[:alnum:]]##/_}#_}%_}(將非alnums 序列轉換為_並刪除最終的前導或尾隨_)。

另一種方法可能是提取所有的 alnums 序列並將它們與 連接起來_,使用這個 hack:

words=()
: ${var//(#m)[[:alnum:]]##/${words[1+$#words]::=$MATCH}}
var=${(j:_:)words}

regexp-replace``[[ $var =~ pattern ]]它本身是一個循環呼叫的可自動載入函式。請注意,因此,它不能與^錨點或單詞邊界或後視運算符(如果使用該rematchpcre選項)一起正常工作:

$ a='aaab'; regexp-replace a '^a' x; echo "$a"
xxxb
$ a='abab'; regexp-replace a '\<ab' '<$MATCH>'; echo $a
<ab><ab>

(在第一個範例中,在該循環^a中依次匹配aaab, aab, , )。ab``b

引用自:https://unix.stackexchange.com/questions/557473