zshパラメータ拡張にはどのモードを使用できますか?

zshパラメータ拡張にはどのモードを使用できますか?

私のzshシェルスクリプトでregexp-replace nname "_{2,}" "_"複数の「_」を1つに正常に減らしましたが、zshを試してみるとパターン${nname//_{2,}/'_'}と一致しないようです。

man zshexpnはい。わからない。これにはワイルドカードパターンが記載されていますが、${name//[^[:alnum:]]/"_"} 私のスクリプトで正しく動作するような他のPOSIX 1003.2正規表現があるようです。

やる気

次のパラメータ拡張を探しています。

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

扱いにくい

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

答え1

${var//pattern/replacement}zshワイルドカードパターンの使用pattern(使用されているものと同じ)ファイル名の生成ワイルドカードとも呼ばれ、shワイルドカードパターンの親セットです。構文はkshglobおよびextendedglobオプションの影響も受けます。もともと${var//pattern/replacement}Kornシェルに由来していました。

あなたの場合はextendedglobそれを有効にすることをお勧めします。これは標準EREよりも多くの機能を提供しますが、いくつかの特殊なケースでは以前のバージョンとの互換性がなくなる可能性があります。set -o extendedglob~/.zshrc

ログインしていることがわかりますinfo zsh 'filename generation'

EREと拡張zshワイルドカード間のマッピングのためのチートシート:

基準sh

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

zsh 拡張子:

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

一部のアドインは標準 ERE では使用できません。

  • ^pattern(否定的な)
  • x~y(とは別に)
  • <12-234>素数範囲一致
  • (#i)大文字と小文字を区別しない一致
  • (#a2)おおよその一致では、最大2つのエラーが許可されます。
  • もっとあります

ワイルドカードパターンがトピックの先頭に固定されているのか、最後に固定されているのかは、使用する演算子によって異なります。

  • Glob、caseパターン[[ string = pattern ]]、および${var:#pattern}すべて固定されています(代わりにf*.txt一致)。foo.txtXfoo.txtY
  • ${var#pattern}そして${var##pattern}最初に固定
  • ${var%pattern)そして${var%%pattern}最後に固定
  • ${var/pattern/repl}固定されていませんが、${var//pattern/repl}(スタート)または(終了)で達成できます。${var/#pattern}${var/%pattern}

(#s)/(ERE)または/(PCRE)と同等に(#e)使用することもできます。^$\A\z

反復演算子(#、、、、、、)が欲張りであるかどうかは、演算子によって異なり、(、欲求、、欲張りではない##*パラメータ拡張フラグ(#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:]]##/_}#_}%_}(alnum以外のシーケンスを変換し_、最後の先行または末尾のシーケンスを削除_)。

_もう1つのアプローチは、次のハッキングを使用してすべてのalnumsシーケンスを抽出し、それを組み合わせることです。

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。)aaabaababb

関連情報