Egrep 和 grep 的区别

我有一个关于 unixgrepegrep的问题。

因为我最近正在学习 unix中的 shell commands,我想知道 grep 和 egrep 之间的区别。

我发现我们可以将 grep 和 egrep 与正则表达式一起使用:

对于 ^,grep 和 egrep 具有相同的含义,即查找在最开始包含给定内容的行。

然而,对于 |,grep,在 |前面没有反斜杠,意味着字符 |,如果我在它前面放一个反斜杠,它会打开它,特殊的意思是找到这条线包含它前面和后面的东西。但是,对于 egrep 来说,情况恰恰相反。|具有 grep 的后一种含义,\|在使用它时具有 grep 的前一种含义。

有人能解释一下原因吗?

58175 次浏览

egrep命令是 grep二进制文件的快捷方式,但是有一个例外: 当 grep作为 egrep被调用时,grep二进制文件激活其内部逻辑以运行,就好像它被调用为 grep -E一样。

区别在于 -E选项支持使用扩展的 regexp 模式。这允许使用元符号,如 +?|。这些不是我们在文字或文件名中使用的普通字符,而是 grep二进制文件本身的控制命令。因此,对于 egrep,字符 |表示逻辑 OR。

因此,例如,您希望列出目录中的文件,并只查看那些包含“ mp4”或“ avi”作为文件扩展名的文件。使用 egrep,你可以做到:

ls | egrep "mp4|avi"

在本例中,|的作用类似于 OR 命令。它将从 ls获取包含“ mp4”或“ avi”字符串的所有名称。如果您使用一个简单的 grep命令运行它,您将什么也得不到,因为 grep不知道诸如 |命令之类的东西。相反,grep将搜索“ mp4 | avi”作为一个完整的文本字符串(使用 烟斗符号)。例如,如果您的目录中有一个名为 |mp4|avi|cool-guy.q2.stats的文件,那么您将使用管道进行简单的 grep搜索。

因此,这就是为什么您应该在 egrep命令中转义 |以实现与 grep相同的效果。转义将屏蔽掉 |命令对于 grep二进制文件的特殊含义。

Grep 命令用于查找文件中包含所需 patran 的行,我们通过放置’’来单独使用元字符

Egrep 等于 grep-E,它是扩展正则表达式,使用{ ,} ,(,) ,| ,? 作为元字符,而不在表达式中给出’

Fgrep 用于查找与 grep-F 相等的固定字符串

Test.txt
文件
瓷砖
(废话)
(废话)

Grep“(f | t) ile”test.txt
(废话)

Grep“(f | t) ile”test.txt
文件
瓷砖

Egrep“(f | t) ile”test.txt
文件
瓷砖

Egrep“(f | t) ile”test.txt
(废话)

Fgrep“(f | t) ile”test.txt
(废话)

Fgrep“(f | t) ile”test.txt
(废话)

摘自 Grep 解释道man页。

grep提供匹配器选择选项。
-E将模式解释为扩展正则表达式
-G将模式解释为基本正则表达式(BRE)。这是没有指定选项时的 违约

变体程序 egrepgrep -E相同。这种变体不被推荐,但是提供给向下兼容使用。

所以,
grep意味着 grep -G
egrep意味着 grep -E

正则表达式模式中的语法有两种解释。区别在于一些特殊字符的行为,如 ?+(){}|

  • BRE (基本正则表达式)-这些字符 不要有特殊的意义,除非前缀有一个反斜杠 \
  • 这些字符是 特殊字符,除非以反斜杠 \作为前缀。

由于 ^grep(BRE)和 egrep(ERE)的解释是相同的,因此它在两者中的工作原理是相同的。
但是,|grep(BRE)和 egrep(ERE)解释方式不同的字符之一,因此它需要根据正则表达式的意图使用 \进行转义。

Grep 和 egrep 的区别是:

Grep

  • 它使用基本正则表达式,这意味着如果你使用 grep 'a|b',它不会使用这个“ |”作为 OR 运算符而不使用这个“”前缀。
  • 它在每个文件中搜索模式。

Egrep

  • 它使用扩展正则表达式,在这里您可以使用类似于 egrep 'a|b'的命令
  • 它按原样处理元字符,不将它们替换为类似 grep 的字符串。

2022年更新: 提到 Ap-osd回答

变种程序 egrepgrep -E是一样的,变种程序不被推荐使用,但是提供给向下兼容使用。

这种情况可能不会持续太久。

这在 Git 2.39(Q42022)中可以看到,它取代了 GNU [ef]grep,因为 GNU 抛出了使用它们的警告。

第37章第90节承诺81580fa犯下764c37第二季,第9集(2022年9月21日) by (sgn)
(由 朱尼奥 · C · 哈马诺 gitster提交 de73968合并,2022年10月7日)

37eb90f79a : t: 将 fgrep的用法转换为“ grep -F

签字人: oàn Tr something n Cotng Danh

尽管 POSIX 指出:

旧的 egrepfgrep命令可能会作为实现扩展支持很多年,从而允许历史应用程序在未修改的情况下进行操作。

GNU grep 3.8开始发出警告:

The egrep and fgrep commands, which have been deprecated since
release 2.5.3 (2007), now warn that they are obsolescent
and should be replaced by grep -E and grep -F.

准备在未来移除它们。

这指的是 2022年10月 grep3.8发布提交951562,其中包括常见问题:

egrepgrep怎么了?

第7版 Unix 有命令 egrepfgrep 是现代 grep -Egrep -F的对应物。

虽然把 grep分成三个程序 对于上世纪70年代的小型计算机、 egrepfgrep没有被 POSIX 标准化,也不再需要。

在当前的 GNU 实现中,egrepfgrep 发出警告,然后表现得像他们的现代同行; 最终,它们将被完全移除。

如果你喜欢旧名字,你可以用你自己的替代品, 例如名为 egrep的 shell 脚本,其中包含以下内容 内容:

#!/bin/sh
exec grep -E "$@@"

有趣的是,同一个 Git 2.39(Q42022)有一个有趣的(Perl)脚本来检测不可移植的 GNU 脚本:

提交2b52163(2022年9月22日) by 阳光艾瑞克(sunshineco)
提交75fc96d(2022年9月23日) by 滨野俊男(gitster)
(由 朱尼奥 · C · 哈马诺 gitster第一季,第375集合并,2022年10月7日)

check-non-portable-shell : 检测过时的 egrep/fgrep

落款: Eric Sunshine

t/check-non-portable-shell.pl

/\b[ef]grep\b/ and err 'egrep/fgrep obsolescent (use grep -E/-F)';

通过阅读本页和其他一些文章,我得到了一个答案,我想我可以提供我自己的看法。底部有个 TL DR。

首先,egrepgrep -E的捷径,fgrepgrep -F的简称。因此,有三种变体,我将讨论它们。

 fgrep string [list of files]
grep -F string [list of files]

在此变体中,string 不是正则表达式。只是一根绳子。没有特殊的字符。如果要搜索文件名 foo.c,可以像这样使用 grep -F foo.c,它将按预期工作。因此,这是 grep 的最简单形式。

grep string [list of files]

在这种形式中,字符串是一个基本的正则表达式。只有某些字符与它们的正则表达式意义一起使用,其他字符必须使用后倾转义。

让我们创建一个简单的示例文件:

File name: foo.c
File name: foo.C
foocc

然后我将运行 grep 两次:

$ grep 'foo.c' foo
File name: foo.c
foocc


$ grep 'foo\.c' foo
File name: foo.c

在第一个示例中,点字符被认为是元字符,因此它既匹配 foo.c中的点,也匹配 foocc中的第一个 c

在第二个示例中,我转义了 dot 字符,删除了它的正则表达式用法,因此它只匹配一个文字点。

我们回头再谈这个,现在来看看 egrep。

egrep string [list of files]
grep -E string [list of files]

在这个例子中,字符串现在是一个扩展的正则表达式。

- 有什么区别吗?-这个在手册里:

在基本正则表达式中,元字符? ,+ ,{ ,| ,(和) 失去了它们的特殊意义; 取而代之的是使用反斜线的版本? , + ,{ ,| ,(和)。

这一切意味着什么?使用 grepgrep -Eegrep,您可以进行完全相同的搜索。区别在于转义字符时发生的情况。

在 BRE (基本正则表达式)中,列表中的字符失去了特殊意义,除非您转义它们。在 ERE (扩展正则表达式)中,如果不想要它们的特殊含义,就必须转义它们。

因此,这三个命令是等价的:

 grep    '\(hello\|goodbye) cruel world+'
egrep   '(hello|goodbye) cruel world\+'
grep -E '(hello|goodbye) cruel world\+'

在第一个示例中,圆括号和管道字符被转义,因此它们成为元字符。也就是说,我们要么打招呼,要么说再见。而且这个加号没有转义,所以它是按照字面意思来理解的(它在上面的特殊列表中)。

最后两个例子是相同的。父字符和管道字符不转义,因此它们仍然是元字符。加号被转义,所以它变成了一个文字。

所以我们只匹配一个字面加字符的行,我们匹配这些:

hello cruel world+
goodbye cruel world+

我们将不会匹配其他任何东西。

因此,回顾一下 ... ... grepgrep -E之间的区别在于,哪些字符需要转义,仅此而已。BRE 有一个非常短的默认元字符列表。ERE 的名单更长。无论使用哪种格式,都可以通过转义来交换特殊字符的含义。

一个观点: 我更喜欢 ERE。我不需要考虑哪些角色是哪些。我只是使用正则表达式和转义特殊字符,如果我需要它们作为文字。