Linux 中的 Grep 命令是什么?为什么要使用它以及它如何工作?
如果您使用Linux进行日常工作或开发和部署软件,那么您一定遇到过grep命令。
在这篇解释文章中,我将告诉您什么是 grep 命令以及它是如何工作的。
什么是 grep?
Grep 是 Unix 和 Linux 系统中的命令行实用程序。它用于在给定文件的内容中查找搜索模式。
看到这个不寻常的名字,您可能已经猜到 grep 是首字母缩写。这至少部分正确,但这取决于您问的是谁。
据可靠消息来源称,该名称实际上源自 UNIX 文本编辑器中的命令ed。其中,输入g/re/p
执行全局 (g) 搜索正则表达式 (re),然后打印 (p) 任何匹配的行。
grep 命令的作用与编辑器中的 g/re/p 命令相同。它对正则表达式进行全局搜索并打印。它在搜索大型文件时速度更快。
这是官方的说法,但你也可能看到它被描述为全局正则表达式(处理器解析器打印机)。说实话,它能做到这一切。|
|
grep 创建背后的有趣故事
Ken Thompson对计算机科学做出了一些令人难以置信的贡献。他帮助创建了 Unix,推广了其模块化方法,并编写了许多程序,包括 grep。
Thompson 开发了 grep 来协助他在贝尔实验室的一位同事。这位科学家的目标是通过研究语言模式来确定《联邦党人文集》的作者(包括亚历山大·汉密尔顿)。这份庞大的工作汇集了 85 篇匿名文章和为捍卫美国宪法而起草的论文。但由于这些文章都是匿名的,这位科学家试图根据语言模式来确定作者。
最初的 Unix 文本编辑器 ed(也是由 Thompson 创建的)由于当时的硬件限制,无法搜索如此大量的文本。因此,Thompson 将搜索功能转变为独立于 ed 编辑器的独立实用程序。
如果你仔细想想,这意味着亚历山大·汉密尔顿在技术上帮助创建了 grep。欢迎在汉密尔顿观看派对上与朋友们分享这个有趣的事实。?
再说一下正则表达式是什么?
正则表达式 (或 regex) 可以看作是一种搜索查询。正则表达式用于识别、匹配或以其他方式管理文本。
不过,正则表达式的功能远不止关键字搜索。它可以用来查找任何可以想象到的模式。使用元字符可以更轻松地找到模式。这些特殊字符使此搜索工具更加强大。
需要注意的是,grep 只是使用正则表达式的工具之一。各种工具都有类似的功能,但元字符和语法可能会有所不同。这意味着了解特定正则表达式处理器的规则非常重要。
grep 的一个实际例子:匹配电话号码
此工具可能会让新手和经验丰富的 Linux 用户望而生畏。不幸的是,即使是电话号码等相对简单的模式也会产生“吓人”的正则表达式字符串。
我想向你保证,当你看到这样的表达式时,没有必要惊慌。一旦你熟悉了正则表达式的基础知识,它就可以为你的计算打开一个充满可能性的新世界。
文化注释:此示例使用美国 (NANP) 电话号码惯例。这些是 10 位数字 ID,分为区号(3 位数字)和唯一的 7 位数字组合,其中前 3 位数字对应于中央电信局(称为前缀),后 4 位称为线路号。因此模式为 AAA-PPP-LLLL。
我创建了一个名为的文件phone.txt
,并写下了同一个电话号码的 4 个常见变体。我将使用 grep 来识别数字模式,无论格式如何。
我还添加了一行不符合表达式的代码,用作控制。最后一行555!123!1234
不是标准的电话号码模式,因此 grep 表达式不会返回该代码。
文件内容phone.txt
如下:
christopher@linux-handbook:~$ cat phone.txt
5551231234
555 123 1234
555-123-1234
(555)-123-1234
555!123!1234
为了“grep”电话号码,我将使用元字符编写正则表达式来隔离相关数据并忽略我不需要的数据。
完整的命令如下所示:
christopher@linux-handbook:~$ grep '\(([0-9]\{3\})\|[0-9]\{3\}\)[ -]\?[0-9]\{3\}[ -]\?[0-9]\{4\}' phone.txt
看起来有点紧张,对吧?让我们将其分解成几个部分,以更好地了解正在发生的事情。
逐段理解正则表达式
首先让我们分离出在电话号码中查找“区号”的 RegEx 部分。
部分重复类似的模式以获取其余数字。需要注意的是,区号有时包含在括号中,因此您需要在此处的表达式中考虑到这一点。
整个区域代码部分的逻辑被封装在一组转义的圆括号中。你可以看到我的代码以 开头\(
,以 结尾\)
。
当您使用方括号时[0-9]
,您就是在让 grep 知道您正在寻找 0 到 9 之间的数字。同样,您可以使用[a-z]
来匹配字母表中的字母。
大括号中的数字{3\}
, 表示方括号中的项恰好匹配三次。
仍然感到困惑?不要紧张。您将从多个角度来看待此示例,以便您有信心继续前进。
让我们尝试用伪代码来看一下区号部分的逻辑。我已将表达式的每个部分分离出来。
区号 RegEx 的伪代码
- \(
- (3 位数字)
- |
- 3 位数字
- \)
希望这样看可以让正则表达式更直观。用通俗的语言来说,您正在寻找 3 位数字。每个数字可以是 0-9,并且区号周围可能有括号,也可能没有括号。
然后,在第一部分的结尾出现了一个奇怪的部分。
- [-]\?
它是什么意思?该\?
符号表示“匹配零个或一个前导字符”。这里,这指的是我们方括号中的内容[ -]
。
换句话说,数字后面可能有连字符,也可能没有。
区号
现在,让我们用实际代码重新构建相同的块。然后,我将添加表达式的其他部分。
- \(
- ([0-9]\{3\})
- |
- [0-9]\{3\}
- \)
- [-]\?
前缀
为了完成电话号码模式,您只需重新利用一些现有的代码即可。
[0-9]\{3\}[ -]\?
您不必担心前缀周围的括号,但是-
前缀和电话号码的行数字之间可能存在或不存在括号。
行号
电话号码的最后一部分不需要我们寻找任何其他字符,但您需要更新表达式以反映额外的数字。
[0-9]\{4\}
就是这样。现在让我们确保表达式包含在引号中,以尽量减少意外行为。
以下是完整表达
christopher@linux-handbook:~$ grep '\(([0-9]\{3\})\|[0-9]\{3\}\)[ -]\?[0-9]\{3\}[ -]\?[0-9]\{4\}' phone.txt
您可以看到结果以颜色突出显示。这可能不是您的 Linux 发行版的默认行为。
额外提示
如果您希望突出显示结果,可以将其添加--color=auto
到命令中。您还可以将其作为别名添加到 shell 配置文件中,这样每次输入时grep
它都会作为 运行grep --color=auto
。
我希望你现在对 grep 命令有了更好的理解。我只举了一个例子来解释这些事情。如果有兴趣,你可以查看这篇文章,了解更多grep 命令的实际示例。
请通过发表评论来提供您对本文的建议。