web-dev-qa-db-ja.com

kshglobをオンにした後でも、zshで!(単一パターン)を使用できないのはなぜですか?

これはbashで動作します:

touch a b c
echo !(a)

上記のスクリプトをzshで(kshglobをオンにして)実行すると、文句が表示されます。

zsh: number expected

aの後に|を追加すると、機能します。

echo !(a|)

どうして?

8
dedowsdi

この場合、パターンの最後にあるため、 bare glob qualifiers と競合するためです。 *(a1)は、最終日に最後にアクセスされたファイルと見なされます。 (a1)はグロブ修飾子として扱われます。したがって、!(a)の場合、zshはaグロブ修飾子(ここでは!というファイルに適用されます)の後に欠落している日数について不平を言います。

zshグロブでは、(...)グループ化は、(foo|bar)の代替として主に使用されるため、|の追加は、末尾の(...)がグロブ修飾子として扱われないようにするための文書化された方法です。

もう1つの文書化された代替方法は、括弧(!((a)))を2つにすることです。または、空のグロブ修飾子(!(a)(-)など)を追加することもできます。

このあいまいさを完全になくすには、bare_glob_qualオプション(set +o bareglobqual)をオフにしてから、グロブ修飾子をextendedglob(#q...)構文(*(#qa1) here)で記述する必要があります。

kshglobオプション( 1998年に追加 とほぼ同じ時期にbashextglobを追加しましたが、bashにはそれ以前に拡張グロブがありませんでした) kshエミュレーションモード(emulate ksh)、zshkshスクリプトを実行できるようにするために、主にkshglobが有効になっていて、bareglobqualは無効です。それが最初に導入されたとき、kshglobを有効にした後、グロブ修飾子を-(...)として指定して、この種の競合を回避する必要がありますが、これにより、混乱が激しくなり、@-(...)ksh93の構文、(#q...)およびbareglobqualオプションは後で導入されました。

zshユーザーは一般に、入力がより簡単で(ほとんどの場合)より強力なzsh独自の拡張グロブ(set -o extendedglob)演算子を好む(kshglobで有効になっているksh88演算子よりもbash -O extglobにもあります)。

たとえば、!(foo)^fooと記述されます。ただし、!(foo|)barに相当するものは、(^(foo|))barのように長くなります。

その他のksh88-> zsh変換:

  • *(x)-> x#
  • +(x)-> x##
  • @(x|y)-> x|y
  • ?(x)-> (x|)

一部のksh93-> zsh変換:

  • ~(i:x)-> (#i)x(大文字と小文字は区別されません)
  • ~(N)x-> x(N)(nullglob、zshで作成)
  • {1,5}(x)-> x(#c1,5)
  • @(foo&bar)-> foo~^barまたは^(^foo|^bar)

一部はzshでのみ見つかります:

  • <1-23>(10進数の範囲)
  • pattern~except
  • pattern(glob-qualifier)(zshグロブのキラー機能)
  • (pattern/)#patternに一致する任意のレベルのサブディレクトリ。**/(*/)#の簡易バージョンも最近ksh93およびbashに追加されました)
  • ***/*(シンボリックリンクに続く再帰的グロビング)。
  • (#a1)foobar(近似マッチング、いくつかのエラーを許可、ここでは1)
  • ...
10