Bashワイルドカードが期待どおりに機能しません。

Bashワイルドカードが期待どおりに機能しません。

これはい宿題の質問:

小文字で始まるが大文字で終わらない2つ以上の文字を含むすべてのファイル名と一致します。

私の解決策がうまくいかない理由を理解できません。

だから私は次のことをしました。

touch aa
touch ha
touch ah
touch hh
touch a123e
touch hX
touch Ax

ls [a-z]*[!A-Z]

出力:

aa  ha

私の質問:「ah」、「hh」、または「a123e」と一致しないのはなぜですか?

答え1

これはロケール質問。あなたのロケールでは(おそらく別のアクセント文字で)[A-Z]拡張されるので、実際にはあなたの例では(そしてあなたの例でのみ)「で終わるファイル」を意味します。[AbBcZ...zZ][^A-Z]a

この予期しない状況を回避するには、LC_COLLATE=C 照合順序がソート順序を担当するロケールの一部であるため、これを行う1つの方法は設定することです。またLC_ALL、設定されている場合は優先順位が適用されますので空にしてください。

$ ls [a-z]*[^A-Z]
aa  ha

$ ( LC_ALL=; LC_COLLATE=C; ls [a-z]*[^A-Z] )
a123e  aa  ah  ha  hh

あるいは、より良い方法は、ロケールを変更するのではなく、代わりに[:lower:]適切なクラスを使用することです。[a-z][:upper:][A-Z]

$ ls [[:lower:]]*[^[:upper:]]
a123e  aa  ah  ha  hh

または、bashのglobasciirangesオプションを使用してください。

$ shopt -s globasciiranges
$ ls [a-z]*[^A-Z]
a123e  aa  ah  ha  hh

$ shopt -u globasciiranges
$ ls [a-z]*[^A-Z]
aa  ha

関連情報