方括号通配中区分大小写

方括号通配中区分大小写

通常,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”。那么:有什么方法可以通配所有以大写字母开头的文件吗?

答案1

在 bash 4.3 及更高版本中,有一个名为 的 shopt 选项globasciiranges

根据shopt 内置 GNU 手册页

globasciiranges
如果设置,则模式匹配括号表达式(请参阅模式匹配)中使用的范围表达式在执行比较时的行为就像在传统 C 语言环境中一样。也就是说,不考虑当前语言环境的整理顺序,因此 'b' 不会在 'A' 和 'B' 之间进行整理,而大写和小写 ASCII 字符将整理在一起。

结果你可以

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

用于shopt -u禁用。

另一种方法是将语言环境更改为 C。您可以使用子 shell 临时执行此操作:

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

您将获得所需的结果,并且当子 shell 完成时,主 shell 的区域设置将保持与之前相同的不变。

另一种选择是不将大括号扩展与bash shopt 选项一起[A-Z]使用。{A..Z}nullglob

通过启用该nullglob选项,如果在路径名扩展期间模式不匹配,则返回空字符串而不是模式本身。
结果,这个将按预期工作:

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

答案2

您可以写出所有大写字母,如下所示:

[ABCDEFGHIJKLMNOPQRSTUVWXYZ]*

或者使用可以使用命名字符类[:upper:]来表示当前中的所有大写字母locale

[[:upper:]]*

正如您所注意到的,在使用范围(如[B-C]相同字母字符的大写和小写)时,它们会相邻排列(根据 的排序规则locale)。

答案3

在字符范围中包含“不直观”的字符(例如在边界为大写字母的范围中包含小写字母)是由于LC_COLLATE区域设置造成的。LC_COLLATE应该表示排序顺序,但它做得很差(对字符串进行排序比语言环境可以做的更复杂)并且没有它你会更好。我建议LC_COLLATE从您的区域设置中删除。如果您要设置LANG、 或LANGUAGE,请不要这样做,只设置您需要的:LC_CTYPELC_MESSAGESLC_TIME

有关区域设置的更多背景信息,请参阅我应该将区域设置设置为什么?这样做会产生什么影响?设置 LC_* 但不设置 LC_ALL

要在脚本中获得可靠的结果(无论用户的设置如何),请设置LC_ALL=C

答案4

echo [cC]* 应该做你想做的,类似 [A-Za-z]*

我来这里是因为我的系统上的通配符刚刚停止了区分大小写,因此我的大量脚本不再正常工作:-(

相关内容