regex egrep和grep之间的区别

8hhllhi2  于 2022-12-14  发布在  其他
关注(0)|答案(6)|浏览(255)

我有一个关于unix中的grepegrep的问题。
因为我最近在研究unix中的shell commands,所以我想知道grep和egrep之间有什么区别。
我发现我们可以用正则表达式来使用grep和egrep。但是,我发现这两个命令之间有些不同:
对于^,grep和egrep具有相同的含义,即查找在最开始处包含给定stuffs的行。
但是,对于|,grep,在|前面没有反斜杠,表示|的字符,如果我在它前面放一个反斜杠,它就会打开它的特殊含义,即查找行包含它前面和后面的内容。但是,对于egrep,相反。当使用grep时,|具有grep的后一种含义,而\|具有grep的前一种含义。
谁能解释一下为什么?

7xzttuei

7xzttuei1#

egrep命令是grep二进制文件的快捷方式,但有一个例外:当grep作为egrep被调用时,grep二进制代码激活其内部逻辑以如同它被称为grep -E那样运行。
不同的是-E选项允许使用扩展的正则表达式模式。这允许使用元符号,如+?|。这些不是普通的字符,我们可能会在单词或文件名中使用,而是grep二进制本身的控制命令。因此,对于egrep,字符|意味着逻辑或。
例如,你想列出一个目录中的文件,并且只查看那些文件扩展名为“mp4”或“avi”的文件。
ls | egrep "mp4|avi"
在这个例子中,|的作用就像一个OR命令。它将从ls中抓取并输出所有包含“mp4”或“avi”字符串的名称。如果你用一个普通的grep命令运行它,你将什么也得不到,因为grep不知道|这样的命令。相反,grep将搜索“mp4| avi”作为一个完整的文本字符串(带有 pipe 符号)。例如,如果您的目录中有一个名为|mp4|avi|cool-guy.q2.stats的文件,您将使用普通的grep通过管道搜索来获得它。
因此,这就是为什么您应该在egrep命令中转义|,以达到与grep相同的效果。转义将屏蔽|命令对grep二进制文件的特殊含义。

fivyi3re

fivyi3re2#

摘录自grep explainedman页面。
grep提供匹配器选择选项。
-E将模式解释为扩展正则表达式(ERE)
-G将模式解释为基本正则表达式(BRE)。这是未指定选项时的 * 默认值 *。
变量程序egrepgrep -E相同。该变量已过时,但提供它是为了向后兼容。
因此,
grep意味着grep -G
egrep隐含grep -E
正则表达式模式中的语法有两种解释,区别在于一些特殊字符的行为:?+(){}|

  • BRE(基本正则表达式)-这些字符 * 没有 * 特殊含义 *,除非 * 前缀为反斜杠\
  • ERE(扩展正则表达式)-这些字符 * 是 * 特殊的,* 除非 * 以反斜杠\为前缀。

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

gmol1639

gmol16393#

grep和egrep的区别在于:

grep

  • 它使用基本正则表达式,这意味着如果您使用grep 'a|b',它将不会使用此“|“作为OR运算符,而不使用此“\”前缀。
  • 它在每个文件中搜索PATTERN。
    电子邮件地址
  • 它使用扩展的正则表达式,在这里您可以使用egrep 'a|b'这样的命令
  • 它将元字符按原样处理,而不像grep那样将它们替换为字符串。
bzzcjhmw

bzzcjhmw4#

grep命令用于查找文件中具有所需patran的行,我们通过放置“\”来分隔元字符
egrep等于grep -E,它是扩展的正则表达式,使用{,},(,),|,?作为元字符,而不在表达式中提供''
fgrep用于查找固定字符串,它等于grep -F
test.txt


(f)|文件
(\f|\t)文件
grep“(f)的形式|文件”test.txt
(f)|文件
测试. txt


egrep“(f)的形式|文件”test.txt


测试. txt
(f)|文件
fgrep“(f)中的一个参数|文件”test.txt
(f)|文件
文件”test.txt
(文件

r1zk6ea1

r1zk6ea15#

2022年更新:已提及的ap-osdanswer
变量程序egrepgrep -E相同。该变量已过时,但提供它是为了向后兼容。
这种情况可能不会持续太久。
这在Git 2.39(Q4 2022)中可以看到,它取代了GNU [ef]grep,因为GNU抛出了它们的使用警告。
参见Đoàn Trần Công Danh ( sgn )commit 37eb90fcommit 81580facommit a764c37commit 2e09272(2022年9月21日)。
(由Junio C Hamano -- gitster --合并到commit de73968,2022年10月7日)
第1011章:t:将fgrep用法转换为“grep -F
签署人:段陈公丹
尽管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.

为将来删除它们做好准备

这是指Oct. 2022 grep 3.8 releasecommit a951562,其中包括常见问题解答:

egrepgrep发生了什么变化?

第7版Unix有命令egrepfgrep,它们是现代的grep -Egrep -F的对应物。
虽然将grep分成三个程序在20世纪70年代的小型计算机上可能有用,但egrepfgrep没有被POSIX标准化,也不再需要。
在当前的GNU实现中,egrepfgrep发出一个警告,然后像它们的现代对应物一样操作;最后,当局计划将它们全部拆除。
如果您喜欢使用旧名称,可以使用您自己的替代名称,例如名为egrep的shell脚本,其中包含以下内容:

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

有趣的是,同一个Git 2.39(Q4 2022)有一个有趣的(Perl)脚本来检测不可移植的GNU脚本:
参见commit 2b52163(2022年9月22日),作者:Eric Sunshine ( sunshineco )
参见commit 75fc96d(2022年9月23日),作者Junio C Hamano ( gitster )
(2022年10月7日由Junio C Hamano -- gitster --合并至commit 1f1f375
第1001章:检测过时egrep/fgrep
签署人:埃里克·桑森
请参阅t/check-non-portable-shell.pl

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

dgenwo3n6#

在阅读这一页和其他几页的时候,我想我应该提供我自己的答案。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

在第一个示例中,点字符被视为 meta字符,因此它与foo.c中的点以及foocc中的第一个c都匹配。
在第二个示例中,我对点字符进行了转义,删除了它的正则表达式用法,因此它只匹配文字点。
我会回来的。现在让我们看看egrep。

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

在这个例子中,string现在是一个扩展的正则表达式。它的工作原理是一样的。
那么,两者之间有什么区别呢?在手册页中有这样的内容:
在基本正则表达式中,元字符?、+、{|、(、和)失去它们的特殊意义;请使用反斜杠形式?、+、{|、(和)。
这意味着什么?使用grepgrep -Eegrep,您可以执行完全相同的搜索。不同之处在于转义字符时会发生什么。
在BRE(基本正则表达式)中,列表中的字符将失去特殊意义,除非对它们进行转义。在ERE(扩展正则表达式)中,如果不希望它们具有特殊意义,则必须对它们进行转义。
因此,这三个命令都是等效的:

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

在第一个例子中,括号和管道字符被转义,所以它们变成了 meta字符,也就是说,我们将匹配hello或goodbye,而加号没有被转义,所以它是字面上的(它在上面的特殊列表中)。
最后两个例子是相同的。父字符和管道字符没有转义,所以它们仍然是 meta字符。加号被转义,所以它变成了文字。
因此,我们只匹配world后面带有文字加号字符的行。我们将匹配以下内容:

hello cruel world+
goodbye cruel world+

我们不会匹配任何其他内容。
grepgrep -E之间的区别在于转义的字符列表,仅此而已。BREs的默认元字符列表非常短。ERE的列表更长。无论使用哪种格式,都可以通过转义来交换特殊字符的含义。
有一点意见:我更喜欢ERE。我不需要考虑哪些字符是哪些字符。我只需要使用正则表达式和转义特殊字符,如果我需要他们作为文字。

相关问题