我有一个关于unix
中的grep
和egrep
的问题。
因为我最近在研究unix
中的shell commands
,所以我想知道grep和egrep之间有什么区别。
我发现我们可以用正则表达式来使用grep和egrep。但是,我发现这两个命令之间有些不同:
对于^
,grep和egrep具有相同的含义,即查找在最开始处包含给定stuffs的行。
但是,对于|
,grep,在|
前面没有反斜杠,表示|
的字符,如果我在它前面放一个反斜杠,它就会打开它的特殊含义,即查找行包含它前面和后面的内容。但是,对于egrep,相反。当使用grep时,|
具有grep的后一种含义,而\|
具有grep的前一种含义。
谁能解释一下为什么?
6条答案
按热度按时间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
二进制文件的特殊含义。fivyi3re2#
摘录自grep explained和
man
页面。grep
提供匹配器选择选项。-E
将模式解释为扩展正则表达式(ERE)-G
将模式解释为基本正则表达式(BRE)。这是未指定选项时的 * 默认值 *。变量程序
egrep
与grep -E
相同。该变量已过时,但提供它是为了向后兼容。因此,
grep
意味着grep -G
egrep
隐含grep -E
正则表达式模式中的语法有两种解释,区别在于一些特殊字符的行为:
?
、+
、()
、{}
和|
。\
。\
为前缀。由于
^
具有grep
(BRE)和egrep
(ERE)的相同解释,因此它在两者中的工作方式相同。但是,
|
是grep
(BRE)和egrep
(ERE)解释不同的字符之一,因此需要根据正则表达式意图使用\
进行转义。gmol16393#
grep和egrep的区别在于:
grep
grep 'a|b'
,它将不会使用此“|“作为OR运算符,而不使用此“\”前缀。电子邮件地址
egrep 'a|b'
这样的命令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
(文件
r1zk6ea15#
2022年更新:已提及的ap-osd的answer
变量程序
egrep
与grep -E
相同。该变量已过时,但提供它是为了向后兼容。这种情况可能不会持续太久。
这在Git 2.39(Q4 2022)中可以看到,它取代了GNU
[ef]grep
,因为GNU抛出了它们的使用警告。参见Đoàn Trần Công Danh (
sgn
)的commit 37eb90f、commit 81580fa、commit a764c37、commit 2e09272(2022年9月21日)。(由Junio C Hamano --
gitster
--合并到commit de73968,2022年10月7日)第1011章:
t
:将fgrep
用法转换为“grep -F
“签署人:段陈公丹
尽管POSIX声明:
旧的
egrep
和fgrep
命令很可能会作为实现扩展被支持很多年,允许历史应用程序未经修改地运行。GNU grep 3.8开始警告:
为将来删除它们做好准备。
这是指Oct. 2022
grep
3.8 release和commit a951562,其中包括常见问题解答:egrep
和grep
发生了什么变化?第7版Unix有命令
egrep
和fgrep
,它们是现代的grep -E
和grep -F
的对应物。虽然将
grep
分成三个程序在20世纪70年代的小型计算机上可能有用,但egrep
和fgrep
没有被POSIX标准化,也不再需要。在当前的GNU实现中,
egrep
和fgrep
发出一个警告,然后像它们的现代对应物一样操作;最后,当局计划将它们全部拆除。如果您喜欢使用旧名称,可以使用您自己的替代名称,例如名为
egrep
的shell脚本,其中包含以下内容:有趣的是,同一个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
dgenwo3n6#
在阅读这一页和其他几页的时候,我想我应该提供我自己的答案。DR位于底部。
首先,
egrep
是grep -E
的缩写,fgrep
是grep -F
的缩写,因此,有三种变体,我将讨论它们。在这个变体中,string不是一个正则表达式。它只是一个字符串。没有特殊字符。如果你想搜索文件名foo.c,你可以像这样使用
grep -F foo.c
,它会像预期的那样工作。因此,这是grep最简单的形式。在这种形式中,你的字符串是一个基本的正则表达式。只有某些字符与它们的正则表达式含义一起使用,其他字符必须用后斜线转义。
让我们创建一个简单的示例文件:
然后运行grep两次:
在第一个示例中,点字符被视为 meta字符,因此它与
foo.c
中的点以及foocc
中的第一个c
都匹配。在第二个示例中,我对点字符进行了转义,删除了它的正则表达式用法,因此它只匹配文字点。
我会回来的。现在让我们看看egrep。
在这个例子中,string现在是一个扩展的正则表达式。它的工作原理是一样的。
那么,两者之间有什么区别呢?在手册页中有这样的内容:
在基本正则表达式中,元字符?、+、{|、(、和)失去它们的特殊意义;请使用反斜杠形式?、+、{|、(和)。
这意味着什么?使用
grep
、grep -E
或egrep
,您可以执行完全相同的搜索。不同之处在于转义字符时会发生什么。在BRE(基本正则表达式)中,列表中的字符将失去特殊意义,除非对它们进行转义。在ERE(扩展正则表达式)中,如果不希望它们具有特殊意义,则必须对它们进行转义。
因此,这三个命令都是等效的:
在第一个例子中,括号和管道字符被转义,所以它们变成了 meta字符,也就是说,我们将匹配hello或goodbye,而加号没有被转义,所以它是字面上的(它在上面的特殊列表中)。
最后两个例子是相同的。父字符和管道字符没有转义,所以它们仍然是 meta字符。加号被转义,所以它变成了文字。
因此,我们只匹配world后面带有文字加号字符的行。我们将匹配以下内容:
我们不会匹配任何其他内容。
grep
和grep -E
之间的区别在于转义的字符列表,仅此而已。BREs的默认元字符列表非常短。ERE的列表更长。无论使用哪种格式,都可以通过转义来交换特殊字符的含义。有一点意见:我更喜欢ERE。我不需要考虑哪些字符是哪些字符。我只需要使用正则表达式和转义特殊字符,如果我需要他们作为文字。