在我的一个实验问题中,我被要求使用管道和 grep 命令列出当前目录中名称仅包含大写字母的所有条目(文件和文件夹)。文件夹必须显示正斜杠。最初,我的解决方案如下所示:
ls -p | grep -e "^[[:upper:]]*\/?$"
我以为我可以用反斜杠保护“/”符号(如echo \*
vs中echo *
)。但是,它没有按预期工作。我的一个朋友建议了以下解决方案:
ls -p | grep -e '^[[:upper:]]*/\?$'
我不知道为什么要这样使用反斜杠。对我来说更奇怪的是,它实际上产生了正确的结果。我想知道是否有人可以解释我的解决方案中的错误在哪里以及为什么第二个版本实际上有效。
答案1
默认情况下,grep
使用基本正则表达式 (BRE),其中?
匹配文字问号。添加反斜杠可使其具有您想要的解释,即量词,表示“前一个表达式出现零次或一次”(即可选地匹配尾随的/
)。
从man grep
:
Basic vs Extended Regular Expressions In basic regular expressions the meta-characters ?, +, {, |, (, and ) lose their special meaning; instead use the backslashed versions \?, \+, \{, \|, \(, and \).
您可以通过添加或标志切换grep
到扩展正则表达式(ERE)模式来实现相同的目的:-E
--extended-regexp
ls -p | grep -E -e '^[[:upper:]]*/?$'
请注意,/
在 BRE 和 ERE 中都是文字 - 因此在任何一种情况下都不需要转义。
您还可以考虑使用-x
来强制执行整行匹配,而无需明确的^
和$
锚点。
请注意(虽然可以作为练习),通常不建议使用管道来选择文件。在 bash 中,您可以考虑使用扩展通配符ls
:grep
shopt -s extglob nullglob
ls -pd *([[:upper:]])