我想了解grep
的工作原理。
当我说grep "hello" *.*
时,grep
是否得到2个参数 - (1)要搜索的字符串,即“hello”和(2)路径*.*
?或者shell会将*.*
转换为grep
可以理解的内容吗?
我在哪里可以获得grep
的源代码?我遇到了这个GNU grep
链接。其中一个README文件说它与unix grep
不同。怎么样?
我想查看FreeBSD版本的grep
以及它的Linux版本(如果它们不同)。
答案 0 :(得分:21)
grep
的力量是自动机理论的神奇之处。 GREP是Global Regular Expression Print的缩写。它的工作原理是构建一个自动机(一个非常简单的“虚拟机”:不是图灵完成);然后它“对输入流执行”自动机。
自动机是节点或状态的图形或网络。国家之间的过渡由受到审查的输入字符决定。像+
和*
这样的特殊自动机通过循环返回自身来工作。像[a-z]
这样的字符类由扇形表示:一个起始节点,每个字符的分支到“辐条”;并且通常辐条对单个最终状态具有特殊的“epsilon过渡”,因此它可以与从正则表达式(搜索字符串)构建的下一个自动机相关联。 epsilon转换允许更改状态,而不会在被搜索的字符串中向前移动。
编辑:看来我没有仔细阅读这个问题。
当您键入命令行时,它首先由shell预处理。 shell执行别名替换和文件名通配。在替换别名(它们就像宏)之后,shell将命令行切换为参数列表(以空格分隔)。此参数列表作为整数计数(通常称为argc)传递给可执行命令程序的main()
函数,并指向以nul结尾的以NULL结尾((void *)0
)数组的指针({{ 1}})char数组。
个别命令会根据自己的意愿使用他们的参数。但是,如果给出'\0'
参数,大多数Unix程序都会打印友好的帮助消息(因为它以减号开头,它被称为选项)。 GNU软件也将接受“长格式”选项-h
。
由于不同版本的Unix程序之间存在很多差异,因此发现程序所需的确切语法的最可靠方法是询问程序本身。如果这不能告诉您需要什么(或者说它太难以理解),您应该接下来检查本地联机帮助页(--help
)。对于gnu软件,您通常可以从man grep
获得更多信息。
答案 1 :(得分:12)
shell执行globbing(从*
表单转换为文件名)。如果你有一个简单的C程序,你可以看到这个:
#include <stdio.h>
int main(int argc, char **argv) {
for(int i=1; i<argc; i++) {
printf("%s\n", argv[i]);
}
return 0;
}
然后像这样运行:
./print_args *
你会看到它打印出匹配的内容,而不是字面上的*
。如果你这样调用它:
./print_args '*'
你会看到它有文字*
。
答案 2 :(得分:5)
shell将“*.*
”扩展为文件名列表,并将扩展的文件名列表传递给grep
等程序。 grep
程序本身不会扩展文件名。
所以,回答你的问题:grep
没有得到2个论点; shell将“*.*
”转换为grep
可以理解的内容。
GNU grep
与Unix grep
的不同之处在于支持额外选项,例如-w
和-B
以及-A
。
在我看来,FreeBSD使用GNU版grep
:
答案 3 :(得分:2)
grep如何看到通配符参数取决于你的shell。 (标准)Bourne shell有一个开关(-f)来禁用文件名globbing(see man pages)。
您可以使用
在脚本中激活此开关set -f