BashとZshはパターンと正規表現の対照をどのように扱いますか?

BashとZshはパターンと正規表現の対照をどのように扱いますか?

次の例を考えてみましょう。

$ bash --version
GNU bash, version 4.4.20(1)-release (x86_64-pc-linux-gnu)
Copyright (C) 2016 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

This is free software; you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
$ LC_COLLATE=C bash --norc -c '[[ B == [a-z] ]] && echo yes || echo no'
no
$ LC_COLLATE=en_GB bash --norc -c '[[ B == [a-z] ]] && echo yes || echo no'
yes
$ LC_COLLATE=C bash --norc -c '[[ B =~ [a-z] ]] && echo yes || echo no'
no
$ LC_COLLATE=en_GB bash --norc -c '[[ B =~ [a-z] ]] && echo yes || echo no'
no

マッチングするときそういうようだ。模様(つまり、=orを使用==) BashはLC_COLLATEに従って対照します。ただし、正規表現と一致する場合(つまり、または使用=~)、BashはPOSIXまたは同様のものに基づいて対照します。

Zshは-少なくとも-すべての場合にzsh 5.8.0.2-dev (x86_64-pc-linux-gnu)印刷します。no

[a-z]パターンや正規表現に使用する場合、それが正確に一致することが保証されますか?

答え1

[a-z]いいえ、正確に一致する保証はありません。

他のロケールでは可能です"C"(ユーティリティがPOSIX規格の場合)。

重要な問題は「範囲」表現(使用法-)にあります。
このような明確なリストは[abcdefghijklmnopqrstuvwxyz]決して失敗しません。


POSIXは正確に要求しますa-zabcdefghijklmnopqrstvwxyzはい。ただし、ロケールがPOSIXデフォルトの場合にのみ適用されます"C"

POSIX仕様では:

POSIXロケールでは、範囲式は、組み合わせシーケンスの2つの要素を含む2つの要素間の組み合わせ要素のセットを表します。範囲式には、他のロケールで指定されていない動作があります。:厳格なコンプライアンスアプリケーションは、スコープ式が有効かどうか、または一致する組み合わせ要素のセットに依存してはいけません。範囲式は、( '-')で区切られた始点と終点として表現する必要があります。

POSIXが特定の意味を要求しても、a-zすべてのアプリケーションは単にPOSIXを無視することを選択できます。

氷山の一角をお見せしましょう。

Python 2.7はASCIIにのみ一致しますa-zが、Python 3.0は他の多くのUnicode文字と一致します。 Bash は 3.2 より前の ASCII にのみマッチングするために使用されました。次に、一致させる文字を決定します。整えるaとは、アプリのロケールに含めることができzますA-Y(通常は含まれていません)。Zbashバージョン5.0+では、globasciirangesオプションを使用して範囲を設定できます。存在する基本的にa-z意図を一致させます。最大ASCII文字。

$ LC_COLLATE=en_GB bash -c 'shopt -u globasciiranges; [[ B == [a-z] ]] && echo yes || echo no'
yes

$ LC_COLLATE=en_GB bash -c 'shopt -s globasciiranges; [[ B == [a-z] ]] && echo yes || echo no'
no

ただし、globasciirangesが有効なbash 5.0であっても、== [a-z]en_GB.utf-8ロケールでは2190文字と一致します。理解を助けるためにa許可される類似文字のリストは次のとおりです。

a a ͣ ⒜ 

関連情報