如何使用 grep 排除模式、文件和目录
已发表: 2022-06-29 自 1974 年以来,Linux grep
命令一直在帮助人们在文件中查找字符串。 但有时grep
太彻底了。 这里有几种方法可以告诉grep
忽略不同的事情。
grep 命令
grep
命令搜索文本文件以查找与您在命令行中提供的搜索模式相匹配的字符串。 grep
的强大之处在于它使用正则表达式。 这些可以让您描述您要查找的内容,而不必明确定义它。
grep
的诞生早于 Linux。 它是在 1970 年代早期在 Unix 上开发的。 它的名字来源于ed
行编辑器中的 g/re/p 键序列(顺便说一下,发音为“ee-dee”)。 这代表全局、常规快速搜索、打印匹配行。
grep
是出了名的——也许是臭名昭著的——彻底而专一。 有时它会搜索您不希望它浪费时间的文件或目录,因为结果可能会让您无法只见树木不见森林。
当然,有一些方法可以控制 grep。您可以告诉它忽略模式、文件和目录,以便 grep 更快地完成搜索,并且您不会被无意义的误报所淹没。
排除模式
要使用grep
进行搜索,您可以通过管道从其他进程(例如cat
)向其输入输入,或者您可以提供文件名作为最后一个命令行参数。
我们正在使用一个短文件,其中包含 Lewis Carroll 的诗歌Jabberwocky的文本。 在这两个示例中,我们正在搜索与搜索词“Jabberwock”匹配的行。
猫jabberwocky.txt | grep "Jabberwock"
grep "Jabberwock" jabberwocky.text
为我们列出了包含与搜索线索匹配的行,每行中的匹配元素以红色突出显示。 这是简单的搜索。 但是,如果我们想排除包含“Jabberwock”这个词的行并打印其余的行怎么办?
我们可以使用-v
(反转匹配)选项来实现这一点。 这列出了与搜索词不匹配的行。
grep -v "Jabberwock" jabberwocky.text
不包含“Jabberwock”的行会在终端窗口中列出。
我们可以根据需要排除尽可能多的术语。 让我们过滤掉任何包含“Jabberwock”的行和任何包含“and”的行。 为此,我们将使用-e
(表达式)选项。 我们需要将它用于我们正在使用的每个搜索模式。
grep -v -e "Jabberwock" -e "and" jabberwocky.txt
输出中的行数相应减少。
如果我们使用-E
(扩展正则表达式)选项,我们可以将搜索模式与“ |
“,在这种情况下并不表示管道,它是逻辑OR
运算符。
grep -Ev "Jabberwock|and" jabberwocky.txt
我们得到的输出与之前的冗长命令完全相同。
如果您想使用正则表达式模式而不是显式搜索线索,则命令的格式是相同的。 此命令将排除以“ACHT”集中任何字母开头的所有行。
grep -Ev "^ACHT" jabberwocky.txt
要查看包含一个模式但也不包含另一个模式的行,我们可以将grep
给grep
。 我们将搜索所有包含单词“Jabberwock”的行,然后过滤掉所有包含单词“ slain ”的行。
grep "Jabberwock" jabberwocky.txt | grep -v "被杀"
排除文件
我们可以让grep
在文件集合中查找字符串或模式。 您可以在命令行上列出每个文件,但是对于许多文件,这种方法无法扩展。
grep "vorpal" verse-1.txt verse-2.txt verse-3.txt verse-4.txt verse-5.txt verse-6.txt
请注意,包含匹配行的文件的名称显示在每行输出的开头。
为了减少打字,我们可以使用通配符。 但这可能违反直觉。 这似乎有效。
grep "vorpal" *.txt
但是,在这个目录下还有其他的TXT文件,与诗歌无关。 如果我们用相同的命令结构搜索“剑”这个词,我们会得到很多误报。
grep "剑" *.txt
我们想要的结果被来自其他具有 TXT 扩展名的文件的大量错误结果所掩盖。
“vorpal”这个词不匹配任何东西,但是“sword”包含在“password”这个词中,因此在一些伪日志文件中多次找到它。
我们需要排除这些文件。 为此,我们将使用--exclude
选项。 要排除名为“vol-log-1.txt”的单个文件,我们将使用以下命令:
grep --exclude=vol-log-1.txt "剑" *.txt
在这种情况下,我们要排除多个名称以“vol”开头的日志文件。 我们需要的语法是:
grep --exclude=vol*.txt "剑" *.txt
当我们使用-R
(dereference-recursive) 选项时, grep
将为我们搜索整个目录树。 默认情况下,它将搜索这些位置的所有文件。 我们可能希望排除多种类型的文件。
在这台测试机器上的当前目录下,有嵌套的目录,其中包含日志文件、CSV 文件和 MD 文件。 这些是我们要排除的所有类型的文本文件。 我们可以为每种文件类型使用--exclude
选项,但是我们可以通过对文件类型进行分组来更有效地实现我们想要的。
此命令排除所有具有 CSV 或 MD 扩展名的文件,以及所有名称以“vol”或“log”开头的 TXT 文件。
grep -R --exclude=*.{csv,md} --exclude={vol*,log*}.txt "sword" /home/dave/data/
排除目录
如果我们要忽略的文件包含在目录中,并且这些目录中没有我们想要搜索的文件,我们可以排除这些整个目录。
这个概念与排除文件的概念非常相似,只是我们使用--exclude-dir
选项并命名要忽略的目录。
grep -R --exclude-dir=backup "vorpal" /home/dave/data
我们已经排除了“backup”目录,但我们仍在搜索另一个名为“backup2”的目录。
我们可以在一个命令中多次使用--exclude-dir
选项也就不足为奇了。 请注意,排除目录的路径应相对于搜索开始的目录给出。不要使用文件系统根目录的绝对路径。
grep -R --exclude-dir=backup --exclude-dir=backup2 "vorpal" /home/dave/data
我们也可以使用分组。 我们可以通过以下方式更简洁地实现相同的目标:
grep -R --exclude-dir={backup,backup2} "vorpal" /home/dave/data
您可以在同一命令中组合文件和目录排除项。 如果要从目录中排除所有文件并从搜索的目录中排除某些文件类型,请使用以下语法:
grep -R --exclude=*.{csv,md} --exclude-dir=backup/archive "frumious" /home/dave/data
有时这是你遗漏的
有时使用grep
感觉就像是在大海捞针。 移除干草堆有很大的不同。
相关:如何在 Linux 上使用正则表达式(regexes)