我想了解grep
是如何工作的。
当我说grep "hello" *.*
, grep
得到2个参数 – (1)被search的string即“hello”和(2)path*.*
? 或者,shell将*.*
转换成grep
可以理解的东西?
我在哪里可以得到grep
源代码? 我碰到这个GNU grep
链接。 其中一个自述文件说它不同于unix grep
。 怎么会这样?
我想看看FreeBSD版本的grep
源码,以及它的Linux版本(如果它们不同)。
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 '*'
你会看到它得到一个文字*
。
grep
的力量是自动机理论的魔力。 GREP是Global Regular Expression Print的缩写。 它通过构建一个自动机(一个非常简单的“虚拟机”:不是图灵完成)。 然后对输入流“执行”自动机。
自动机是节点或状态的图形或网络。 状态之间的转换是由输入字符审查。 像+
和*
这样的特殊自动机器可以通过转换回自己的工作。 像[az]
这样的字符类是由一个风扇来表示的:一个起始节点为每个字符分支到“辐条”; 通常辐条有一个特殊的“epsilon过渡”到一个单一的最终状态,所以它可以链接到正则表达式(搜索字符串)的下一个自动机。 epsilon转换允许状态改变,而不会在被搜索的字符串中向前移动。
编辑:看来我没有仔细阅读这个问题。
当你输入一个命令行时,它首先由shell进行预处理。 shell执行别名替换和文件名匹配。 在替换别名之后(它们就像宏一样),shell将命令行切成一个参数列表(以空格分隔)。 这个参数列表作为一个整数(通常称为argc)和一个指向NULL终止( (void *)0
)数组的终止( '\0'
)的指针传递给可执行命令程序的main )char数组。
不管他们希望如何,单个命令都会使用他们的参数 但是如果给定-h
参数,大多数Unix程序将打印一个友好的帮助信息(因为它以一个减号开头,所以称为一个选项)。 GNU软件也将接受一个“长形”选项 – 帮助。
由于不同版本的Unix程序之间存在很大差异,因此发现程序所需的确切语法的最可靠方法是询问程序本身。 如果没有告诉你需要什么(或者太难理解),那么你应该检查当地的 manpage( man grep
)。 而对于GNU软件,你通常可以从info grep
获得更多的信息。
shell将' *.*
'展开成文件名列表,并将展开的文件名列表传递给程序(如grep
。 grep
程序本身不会扩展文件名。
所以,在回答你的问题: grep
不会得到2个参数; shell将' *.*
'转换成grep
可以理解的东西。
GNU grep
与Unix grep
不同,它支持额外的选项,比如-w
和-B
和-A
。
在我看来,FreeBSD使用的是GNU版本的grep
:
grep如何看到通配符参数取决于你的shell。 (标准)Bourne shell有一个开关(-f)来禁用文件名称通配符 ( 参见手册页 )。
你可以用脚本激活这个开关
set -f