Grep和正则表达式:如何有效使用它们?
如果您使用linux一段时间了,您应该已经了解grep – global regular expression print,这是一个可以用于搜索文件和目录的文本处理工具。对于linux高级用户来说,它非常有用。然而,如果不使用正则表达式,使用它可能会限制其功能。
但是什么是正则表达式?
正则表达式是可以用于改进grep搜索功能的正则表达式。正则表达式按定义是高级的输出过滤模式。通过实践,您可以有效地使用正则表达式,因为您也可以将其与其他linux命令一起使用。
在我们的教程中,我们将学习如何有效地使用grep和正则表达式。
先决条件
使用带有正则表达式的grep需要良好的linux知识。如果您是初学者,那么请查看我们的linux指南。
您还需要访问运行linux操作系统的笔记本电脑或计算机。您可以使用任何您喜欢的linux发行版。而且,如果您有一台windows机器,您仍然可以使用带有wsl2的linux。请查看我们对此的详细说明here。
访问命令行/终端允许您运行我们的grep / regex教程中提供的所有命令。
此外,您还需要访问一个文本文件(或多个),您需要在其中运行示例。我使用chatgpt生成了一堆文本,让它写一些关于技术的内容。我使用的提示如下。
“在技术方面生成400个字。它应该包括大部分技术。此外,请确保在文本中重复使用技术名称。”
生成文本后,我将其复制并保存在tech.txt文件中,我们将在整个教程中使用它。
最后,必须具备对grep命令的基本理解。您可以查看16个grep命令示例来更新您的知识。我们还将简要介绍grep命令,以帮助您入门。
grep命令的语法和示例
grep 命令的语法很简单。
$ grep -options [regex/pattern] [files]
正如您所注意到的,它期望一个模式和您要运行该命令的文件列表。
有很多可用的grep选项可以修改其功能。这些选项包括:
- – i: 忽略大小写
- -r: 执行递归搜索
- -w: 仅查找整个单词
- -v: 显示所有不匹配的行
- -n: 显示所有匹配行的行号
- -l: 打印文件名
- –color: 彩色结果输出
- -c: 显示所使用模式的匹配计数
#1. 查找整个单词
您需要在grep中使用-w参数进行整个单词搜索。通过使用它,您可以绕过与给定模式匹配的任何字符串。
$ grep -w ‘tech|5g’ tech.txt
如您所见,该命令的输出结果是在整个文本中搜索了两个单词“5g”和“tech”。然后,它用红色标记它们。
在这里,|管道符号被转义,以便grep不将其处理为元字符。
#2. 大小写不敏感的搜索
要进行大小写不敏感的搜索,请使用带有-i参数的grep命令。
$ grep -i ‘tech’ tech.txt
该命令搜索任何不区分大小写的“tech”字符串的实例,无论是完整的单词还是其中的一部分。
#3. 非匹配行搜索
要显示不包含给定模式的所有行,需要使用-v参数。
$ grep -v ‘tech’ tech.txt
输出显示所有不包含单词“tech”的行。您还将看到空行。这些行是段落之后的行。
#4. 递归搜索
要进行递归搜索,请使用带有-r参数的grep命令。
$ grep -r ‘error|warning’ /var/log/*.log
#output
/var/log/bootstrap.log:2023-01-03 21:40:18 url:http://ftpmaster.internal/ubuntu/pool/main/libg/libgpg-error/libgpg-erro 0_1.43-3_amd64.deb [69684/69684] -> "/build/chroot//var/cache/apt/archives/partial/libgpg-error0_1.43-3_amd64.deb" [1]
/var/log/bootstrap.log:dpkg: warning: parsing file '/var/lib/dpkg/status' near line 5 package 'dpkg':
/var/log/bootstrap.log:dpkg: warning: parsing file '/var/lib/dpkg/status' near line 5 package 'dpkg':
/var/log/bootstrap.log:dpkg: warning: parsing file '/var/lib/dpkg/status' near line 24 package 'dpkg':
/var/log/bootstrap.log:dpkg: warning: parsing file '/var/lib/dpkg/status' near line 24 package 'dpkg':
/var/log/bootstrap.log:dpkg: warning: ignoring pre-dependency problem!
grep命令在/var/log目录中递归搜索两个词“error”和“warning”。这是一个方便的命令,可以了解日志文件中的任何警告和错误。
grep和正则表达式:定义及示例
由于我们正在使用正则表达式,因此您需要知道正则表达式提供三种语法选项。其中包括:
- 基本正则表达式(bre)
- 扩展正则表达式(ere)
- perl兼容正则表达式(pcre)
grep命令使用bre作为默认选项。因此,如果要使用其他正则表达式模式,您需要提及它们。grep命令还按照原样处理元字符。因此,如果您使用诸如?、+、)之类的元字符,则需要使用反斜杠()命令对它们进行转义。
grep与正则表达式的语法如下。
$ grep [regex] [filenames]
让我们通过以下示例来看看grep和正则表达式的运作方式。
#1. 文字匹配
要进行文字匹配,您需要提供一个字符串作为正则表达式。毕竟,一个单词也是一个正则表达式。
$ grep "technologies" tech.txt
同样,您还可以使用精确匹配来查找当前用户。要这样做,请运行:
$ grep bash /etc/passwd
#输出
root:x:0:0:root:/root:/bin/bash
nitt:x:1000:1000:,,,:/home/nitt:/bin/bash
这将显示可以访问bash的用户。
#2. 锚点匹配
锚点匹配是一种使用特殊字符进行高级搜索的有用技术。在正则表达式中,有不同的锚点字符,您可以使用它们来表示文本中的特定位置。这些包括:
- ‘^’ 尖号符号:尖号符号匹配输入字符串或行的开头,并查找一个空字符串。
- ‘$’ 美元符号:美元符号匹配输入字符串或行的结尾,并查找一个空字符串。
另外两个锚点匹配字符包括‘ b’字边界和‘ b’非字边界。
- ‘ b’ 字边界:使用 b,您可以断言一个单词和一个非单词字符之间的位置。简单来说,它可以让您匹配完整的单词。这样,您可以避免部分匹配。您还可以使用它来替换单词或计算字符串中单词出现的次数。
- b 非字边界:它与正则表达式中的b字边界相反,它断言的是一个位置,该位置不在两个单词或非单词字符之间。
让我们通过示例来更清楚。
$ grep ‘^from’ tech.txt
使用尖号需要以正确的大小写输入单词或模式。这是因为它区分大小写。因此,如果运行以下命令,它将不会返回任何结果。
$ grep ‘^from’ tech.txt
同样,您还可以使用$符号找到与给定模式、字符串或单词匹配的句子。
$ grep ‘technology.$' tech.txt
您还可以同时使用^和$符号。让我们看下面的例子。
$ grep “^from | technology.$” tech.txt
如您所见,输出包含以“from”开头的句子和以“technology”结尾的句子。
#3. 分组
如果您想同时搜索多个模式,您需要使用分组。它可以帮助您创建包含字符和模式的小组,您可以将其视为单个单元。例如,您可以创建一个包含术语‘t’、‘e’、‘c’、‘h’的组(tech)。
为了更清楚地了解,请看一个示例。
$ grep 'technol(ogy)?' tech.txt
通过分组,您可以匹配重复的模式、捕获组,并搜索替代项。
使用分组进行替代搜索
让我们看一个替代搜索的示例。
$ grep "(tech|technology)" tech.txt
如果你想在一个字符串上执行搜索操作,那么你需要用管道符传递它。让我们看下面的例子。
$ echo "tech technological technologies technical" | grep "(tech|technology)"
#output
"tech technological technologies technical"
捕获组、非捕获组和重复模式
那捕获组和非捕获组呢?
你需要在正则表达式中创建一个组,并将其传递给字符串或文件以进行捕获组。
$ echo 'tech655 tech655nical technologies655 tech655-oriented 655' | grep "(tech)(655)"
#output
tech655 tech655nical technologies655 tech655-oriented 655
至于非捕获组,你需要在括号中使用 ?:。
最后,我们有重复的模式。你需要修改正则表达式以检查重复的模式。
$ echo 'teach tech ttrial tttechno attest' | grep '(t+)'
#output
'teach tech ttrial tttechno attest'
在这里,正则表达式查找一个或多个“t”字符的实例。
#4. 字符类
使用字符类,你可以轻松编写正则表达式。这些字符类使用方括号。一些众所周知的字符类包括:
- [:digit:] – 0到9的数字
- [:alpha:] – 字母字符
- [:alnum:] – 字母数字字符
- [:lower:] – 小写字母
- [:upper:] – 大写字母
- [:xdigit:] – 十六进制数字,包括0-9、a-f、a-f
- [:blank:] – 空白字符,如制表符或空格
等等!
让我们看看其中一些的示例。
$ grep [[:digit]] tech.txt
$ grep [[:alpha:]] tech.txt
$ grep [[:xdigit:]] tech.txt
#5. 量词
量词是元字符,是正则表达式的核心。它们允许你匹配确切的出现次数。让我们看看它们。
- * → 零个或多个匹配
- + → 一个或多个匹配
- ? → 零个或一个匹配
- {x} → x个匹配
- {x, } → x个或更多匹配
- {x,z} → 从x到z个匹配
- {, z} → 最多z个匹配
$ echo 'teach tech ttrial tttechno attest' | grep -e 't+'
#output
'teach tech ttrial tttechno attest'
在这里,它搜索一个或多个匹配项的t字符实例。在这里,-e代表扩展的正则表达式(我们稍后会讨论)。
#6. 扩展的正则表达式
如果您不想在正则表达式模式中添加转义字符,您必须使用扩展的正则表达式。它消除了添加转义字符的需要。为此,您需要使用-e标志。
$ grep -e 'in+ovation' tech.txt
#7. 使用pcre进行复杂搜索
pcre(perl兼容正则表达式)让您可以做比编写基本表达式更多的事情。例如,您可以编写“d”,它表示[0-9]。
例如,您可以使用pcre搜索电子邮件地址。
echo "contact me at [email protected]" | grep -p "b[a-za-z0-9._%+-]+@[a-za-z0-9.-]+.[a-za-z]{2,}b"
#output
contact me at [email protected]
在这里,pcre确保模式匹配。类似地,您还可以使用pcre模式来检查日期模式。
$ echo "the sparkain site launched on 2023-07-29" | grep -p "bd{4}-d{2}-d{2}b"
#output
the sparkain site launched on 2023-07-29
该命令找到了以yyyy-mm-dd格式的日期。您可以修改它以匹配其他日期格式。
#8. 选择
如果您想要备用匹配项,可以使用转义的竖线字符(|)。
$ grep -l ‘warning|error’ /var/log/*.log
#output
/var/log/alternatives.log
/var/log/bootstrap.log
/var/log/dpkg.log
/var/log/fontconfig.log
/var/log/ubuntu-advantage.log
/var/log/upgrade-policy-changed.log
输出列出了包含“warning”或“error”的文件名。
最后的话
这就是我们的grep和正则表达式指南的结束。您可以广泛地使用grep与正则表达式来精确搜索。正确使用可以节省大量时间,并有助于自动化许多任务,特别是如果您将它们用于编写脚本或通过文本进行搜索。
接下来,请查看常见的linux面试问题和答案。