grep:使用方括号匹配特定字符

jxh*_*hyc 1 shell grep quoting regular-expression wildcards

所以我正在尝试使用这些资源来发挥 grep 的力量

我目前遇到的问题是它似乎没有按我的预期工作。所以我有一个包含foo.txt的 demo.txt 文件,我使用这个代码来搜索它: grep [a-z][a-z]o.txt demo.txt但它返回空。zsh: no matches found: [a-z][a-z]o.txt 不知道是不是我对方括号用法的理解有误?

这是图片:

在此处输入图片说明

ter*_*don 12

因为您没有引用要传递给的正则表达式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

Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)

这一次,引号保护壳,它通过它的模式为是grepgrep反过来把它理解成一个正则表达式的意思是“任何两个小写字母,那么o,那么任何其它字符,并且结尾txt”。这是一个重要的细节,因为.在正则表达式中意味着“任何字符”。所以你真正想要的是:

grep '[a-z][a-z]o\.txt' demo.txt 
Run Code Online (Sandbox Code Playgroud)

\.“越狱”中.,使其只匹配字面点,不再意味着“任何字符”。所以,总是引用你的正则表达式并小心.

最后,这是使用扩展正则表达式编写此代码的另一种方法:

$ grep -E '[a-z]{2}o\.txt' demo.txt      
foo.txt
Run Code Online (Sandbox Code Playgroud)

1请参阅正则表达式的定义是什么?有关 globs 与正则表达式的更多详细信息。