通常,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
:
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_CTYPE
、LC_MESSAGES
、LC_TIME
。
有关区域设置的更多背景信息,请参阅我应该将区域设置设置为什么?这样做会产生什么影响?和设置 LC_* 但不设置 LC_ALL
要在脚本中获得可靠的结果(无论用户的设置如何),请设置LC_ALL=C
。
答案4
echo [cC]* 应该做你想做的,类似 [A-Za-z]*
我来这里是因为我的系统上的通配符刚刚停止了区分大小写,因此我的大量脚本不再正常工作:-(