$ ls -l /bin/*grep
lrwxrwxrwx 1 root root 4 2010-06-09 02:56 /bin/egrep -> grep
lrwxrwxrwx 1 root root 4 2010-06-09 02:56 /bin/fgrep -> grep
-rwxr-xr-x 1 root root 85060 2007-01-23 02:00 /bin/grep
$ echo 'hello' | grep -q 'l{2}' && echo YES || echo NO
NO
$ echo 'hello' | egrep -q 'l{2}' && echo YES || echo NO
YES
在我的系统中,egrep
是grep
的符号链接,但它们的行为却不同。为什么呢?
答案 0 :(得分:3)
grep
将通过查看argv[0]
来检查其调用。
这是一个简短的演示程序:
> cat someprogram.cpp
#include <iostream>
int main(int argc, char* argv[])
{
std::cout << "Shall behave as " << argv[0] << "." << std::endl;
}
构建
> make someprogram
g++ someprogram.cpp -o someprogram
建立符号链接:
> ln -s someprogram some_other_program
运行一个:
> ./someprogram
Shall behave as ./someprogram.
运行两个:
> ./some_other_program
Shall behave as ./some_other_program.
Gnu grep
是free和开源软件,因此您可以自由查看the source。
答案 1 :(得分:2)
因为可执行文件会检查argv[0]
的值并相应地调整其行为。
答案 2 :(得分:1)
因为POSIX说egrep
相当于grep -E
而不是grep
,fgrep
相当于grep -F
而不是grep
}。如果您希望grep
的行为与egrep
相同,请使用grep -E
,依此类推。还有大约40年的先例问题。
答案 3 :(得分:0)
除正则表达式引擎外,功能相同;通过创建库(这种情况下更常见的方法)或使用检查其名称(argv[0]
)的单个二进制文件来确定请求的行为,共享代码是有意义的。 (第三种可能性是使用单个名称并使用选项来选择不同的行为。这就是git
和tar
之类的命令;单个命令是“接口”但你得到的通过指定不同的行为来完全不同的行为。)
存在明显命令的原因很长,可以追溯到Unix的早期阶段。简单的旧grep
是最早的正则表达式实现之一,随着开发人员对这个特定问题领域的理解得到改进,具有新功能的新工具也得到了发展。出于向后兼容性的原因,这些新功能无法简单地集成到grep
(这会改变其行为),因此新命令具有新名称。当POSIX开始标准化时,grep
,egrep
和fgrep
之间的分工已经确立,尽管事后看来,你可以说至少其中一个是多余的。