所以我正在使用这个来尝试 grep 的强大功能资源
我目前遇到的问题是它似乎没有按我的预期工作。所以我有一个 demo.txt 文件,其中包含foo.txt,我使用这段代码来搜索它:
grep [a-z][a-z]o.txt demo.txt
但它返回空。zsh: no matches found: [a-z][a-z]o.txt
我想知道我对方括号使用的理解是否错误?
这是图片:
答案1
因为您没有引用要传递给的正则表达式grep
,所以它被 shell 捕获,并且 shell 尝试扩展它前打电话grep
。现在,您使用的正则表达式恰好也是有效的 shell glob 模式1,这意味着“列出当前文件夹中名称为任意两个字符,后跟字符串的所有文件或目录o.txt
”。如果当前目录包含与该 glob 匹配的任何文件或子目录,则该 glob 将扩展到匹配的文件名:
$ ls
abo.txt demo.txt
$ cat demo.txt
foo.txt
$ set -x
$ grep [a-z][a-z]o.txt demo.txt
+zsh:7> grep abo.txt demo.txt
告诉显示它运行的实际命令set -x
。zsh
如您所见,[a-z][a-z]o.txt
扩展为匹配的文件名:abo.txt
,并且那是传递给 的内容grep
。
现在,您的目录中实际上没有任何匹配的文件名,这意味着zsh
将模式扩展为空字符串,甚至grep
根本没有启动。这就是错误的原因zsh: no matches found: [a-z][a-z]o.txt
。那是 zsh 告诉您它无法将 glob 扩展到任何匹配的文件。
最后,如果您正确引用该模式,将会发生以下情况:
$ grep '[a-z][a-z]o.txt' demo.txt
+zsh:12> grep '[a-z][a-z]o.txt' demo.txt
foo.txt
这次,引号保护了模式免受 shell 的影响,shell 通过了它按原样togrep
并grep
反过来将其解释为正则表达式,意思是“任意两个小写字母,然后是o
,然后任何其他字符,并以“结尾txt
。这是一个重要的细节,因为.
在正则表达式中意味着“任何字符”。所以你真正想要的是:
grep '[a-z][a-z]o\.txt' demo.txt
“转义\.
”,.
使其仅匹配文字点,不再表示“任何字符”。因此,请始终引用正则表达式并小心.
!
最后,这是使用扩展正则表达式编写此代码的另一种方法:
$ grep -E '[a-z]{2}o\.txt' demo.txt
foo.txt
1参见正则表达式的定义是什么?有关 glob 与正则表达式的更多详细信息。