web-dev-qa-db-ja.com

大括弧グロビングにおける大文字小文字の区別

通常、bashグロビングでは大文字と小文字が区別されます。

$ echo c*
casefix.pike cdless chalices.py charconv.py chocolate.pike circum.py clip.pike cpustats.pike crop.pike cwk2txt.py
$ echo C*
CarePackage.md ChocRippleCake.md Clips

角括弧を使用しても、これは変更されないようです。

$ echo [c]*
casefix.pike cdless chalices.py charconv.py chocolate.pike circum.py clip.pike cpustats.pike crop.pike cwk2txt.py
$ echo [C]*
CarePackage.md ChocRippleCake.md Clips

ハイフンが使用されている場合でも、変更されません。

$ echo [c-c]*
casefix.pike cdless chalices.py charconv.py chocolate.pike circum.py clip.pike cpustats.pike crop.pike cwk2txt.py
$ echo [C-C]*
CarePackage.md ChocRippleCake.md Clips

しかし、文字は散在しています:

$ echo [B-C]*
CarePackage.md casefix.pike cdless chalices.py charconv.py chocolate.pike ChocRippleCake.md circum.py clip.pike Clips cpustats.pike crop.pike cwk2txt.py
$ echo [b-c]*
beehive-anthem.txt bluray2mkv.pike branch branchcleanup.pike burdayim.pike casefix.pike cdless chalices.py charconv.py chocolate.pike circum.py clip.pike cpustats.pike crop.pike cwk2txt.py

これは、ハイフンがロケール順「AaBbCcDd」を使用していることを示唆しています。だから:大文字で始まるすべてのファイルをグロブする方法はありますか?

10
rosuav

Bashバージョン4.3以降には、globasciirangesというshoptオプションがあります。

shopt組み込みのgnuのmanページによると

globasciiranges
設定すると、パターンマッチングの括弧式(パターンマッチングを参照)で使用される範囲式は、比較を実行するときに従来のCロケールであるかのように動作します。つまり、現在のロケールの照合シーケンスは考慮されないため、「b」は「A」と「B」の間で照合されず、大文字と小文字のASCII文字は一緒に照合します。

結果として、

$ shopt -s globasciiranges 
$ echo [A-Z]*

無効にするにはshopt -uを使用します。

別の方法は、ロケールをCに変更することです。これは、サブシェルを使用して一時的に行うことができます。

$ ( LC_ALL=C ; printf '%s\n' [A-Z]*; )

必要な結果が得られ、サブシェルが終了しても、メインシェルのロケールは以前と同じままです。

もう1つの方法は、[A-Z]の代わりに、ブレース展開{A..Z}nullglob bashショップオプションと共に使用することです。

nullglobオプションを有効にすると、パス名の展開中にパターンが一致しない場合、パターン自体ではなくnull文字列が返されます。
その結果、これは期待どおりに機能します:

$ shopt -s nullglob;printf '%s\n' {A..Z}*
12
George Vasiliou

すべて大文字で書くことができます:

[ABCDEFGHIJKLMNOPQRSTUVWXYZ]*

または、名前付き文字クラス[:upper:]を使用して、現在のlocaleのすべての大文字を表すことができます。

[[:upper:]]*

お気づきのとおり、[B-C]のような範囲を使用している間、同じアルファベット文字の大文字と小文字は(localeの照合順序に従って)隣接して配置されています。

5
heemayl

境界が大文字である範囲に小文字を含めるなど、「直感的でない」文字を文字範囲に含めるのは、LC_COLLATEロケール設定が原因です。 LC_COLLATEは並べ替え順序を示すことになっていますが、これはうまく機能せず(文字列の並べ替えは、ロケールで可能なことよりも複雑です)、それなしで使用することをお勧めします。ロケール設定からLC_COLLATEを削除することをお勧めします。 LANG、またはLANGUAGEを設定する場合は、これを行わず、必要なものだけを設定してください:LC_CTYPELC_MESSAGESLC_TIME

ロケールの背景については、 ロケールを何に設定すればよいですか、そうすることの意味は何ですか? および LC_ALLではなくLC_ *を設定 を参照してください。

ユーザーの設定に関係なくスクリプトで信頼できる結果を得るには、LC_ALL=Cを設定します。

セットする:

shopt -u nocaseglob

Bashのmanページから:

>     nocaseglob
>         If  set,  bash matches filenames in a case-insensitive
>         fashion when performing pathname expansion (see Pathname
>          Expansion above).

'globasciiranges'を設定した場合、utf-8のような非ASCII文字がどうなるかわかりません

0
Udi

echo [cC] *は同様に[A-Za-z] *を実行します。

私のシステムでのグロビングはstoppedで大文字と小文字が区別されるため、ここにいます。つまり、スクリプトのロードは、本来あるべきように機能しません:-(

0
user208007