服务器之家:专注于服务器技术及软件下载分享
分类导航

Linux|Centos|Ubuntu|系统进程|Fedora|注册表|Bios|Solaris|Windows7|Windows10|Windows11|windows server|

服务器之家 - 服务器系统 - Linux - Linux文件处理三剑客之grep

Linux文件处理三剑客之grep

2023-11-27 18:25未知服务器之家 Linux

背景 grep命令最初是由美国计算机科学家肯·汤普逊(Ken Thompson)在1974年发明, 为了让用户全局搜索所有匹配的内容并打印它们,所以使用 g/regularexpression/p, 简单地写成 g/re/p( globally search a regular expression and print ) 。后来也可以

背景

grep命令最初是由美国计算机科学家肯·汤普逊(Ken Thompson)在1974年发明, 为了让用户全局搜索所有匹配的内容并打印它们,所以使用 g/regularexpression/p, 简单地写成 g/re/p( globally search a regular expression and print。后来也可以解释为"Global Regular Expression Print"(全局正则表达式打印)的首字母缩写。

肯·汤普逊发明grep命令的主要动机是为了提供一种强大而灵活的文本搜索工具,以满足Unix操作系统用户处理文本数据的需求。在当时,Unix系统的用户需要一种能够快速搜索文本文件中特定模式的工具,以便在处理文本数据时能够高效地定位和提取所需的信息。肯·汤普逊意识到,为了提高Unix系统的实用性,需要一种能够灵活处理文本数据的工具,而grep命令的发明正是为了满足这一需求。


格式

grep命令格式较为简单,grep [OPTIONS] PATTERN [FILE/FOLD...],其中 :

  • OPTIONS为选项

  • PATTERN 为搜索模式

  • FILE 为文件名;如果使用-r递归搜索的时候,可以选择某个文件夹( FOLD

* 注:如果省略 FILE/FOLD,则从标准输入读取内容


参数

本文仅介绍常用参数,如果读者有兴趣了解更多参数,请运行“man grep”或者“grep --help”查看。

  • -i:ignore 忽略大小写

  • -c:count 取行数

  • -w: word 匹配单词

  • -E:extended 正则

  • -P:perl 正则

  • -l:list 列出包含关键字的文件

  • -A:after 取出匹配行以及后续行

  • -B:before 取出匹配行以及前续行

  • -C:取出匹配行的上下行

  • -R:在目录下搜索,比如grep 'abc' ./,表示在当前目录下所有文件进行查找

  • -v:invert 排除

  • -n:number 显示行号

  • -o:only matching 只显示匹配到的内容

  • -r:recursive 递归式搜索

grep的参数是比较多并且复杂的,但无论如何,grep命令的本质还是在于“文件内容的搜索”,而不是“文件名的搜索”。


返回值

  • 0 :表示成功

  • 1 :表示所提供的文件无法找到匹配的pattern

  • 2 :表示查找地点不对


实战

  • 搜索出当前系统下“nologin”的用户信息

grepnologin/etc/passwd

Linux文件处理三剑客之grep

*注:grep只是将包括"nologin"关键字的整行给输出来,而不考虑"nologin"在该行的位置。也就是说,如果有一个用户叫做"nologin1"但是它又是可以login的,那通过上述grep命令,同样也能获取到该行(而这并非一个有效的行)

所以,如果要准确查询出系统下“nologin”的用户信息,需要保证"nologin"出现在行尾,对上述命令进行改进后:

grep'nologin$'/etc/passwd

*注:grep搜索时,^表示开头,$表示结尾


  • 搜索出当前文件夹下有哪些子文件夹

ls-l|grep^d

Linux文件处理三剑客之grep

  • 搜索出系统中ifconfig配置的ip信息

ifconfig|grep-winet

Linux文件处理三剑客之grep

*注:如果使用了-w选项,那有单独inet关键字的行会被搜索出来,但是inetabc的行,不会被匹配

同样,如果为了更精确搜索配置的ip信息,应该以每行开头为“多个空格加inet”这样的形式进行检索,命令如下:

ifconfig|grep'^[]*inet'

*注:上述命令中,[ ]代表一个空格字符,*表示重复前面0个或者多个;如果[abc]*,表示“ 任意abc字符中的一个”重复0次或者多次,所以[abc]*既可以匹配a或者b或者c,也可以匹配abc或者aaa或者abcabc,同样也能匹配aabccc


  • 搜索出系统中ifconfig配置的ip信息,以及对应的网卡名称

为了检索出上述内容,用户需要首先了解ifconfig输出的信息:在正常ifconfig的输出中,inet上一行的内容,即是对应的网卡名称。

ifconfig|grep-B1'^[]*inet'

Linux文件处理三剑客之grep

* 注:如果-B2,代表将匹配行上面2行同时打印出来


  • 检索出/proc/cpuinfo中,关键字“processor”在文件中的行号

grep-n'processor'/proc/cpuinfo

Linux文件处理三剑客之grep

*注:上述输出结果中,左右绿色部分,即为关键字在源文件中的行号

同样,如果需要统计关键字“processor”在文件/proc/cpuinfo中一共出现了多少次,可以运行如下命令统计:

grep-c'processor'/proc/cpuinfo

*注:如上命令为统计x86系统中处理器的个数


  • 在/proc/cpuinfo中检索出包含关键字“processor”往下5行的内容,但需要排除掉有关键字“model”的行

首先,通过-A5可以搜索出关键字往下5行信息,grep -A5 'processor' /proc/cpuinfo

Linux文件处理三剑客之grep

如果需要再排除掉含有关键字“model”的行,通过管道进行二次搜索即可:

grep-A5'processor'/proc/cpuinfo|grep-v'model'


  • 在/var/log下,针对所有messages的log,搜索出包含关键字fail的文件(忽略fail的大小写)

grep -i -l 'fail' /var/log/messages*

Linux文件处理三剑客之grep

*注:如果需要在多个文件中搜索,可以grep 'xxx' file1 file2,或者grep 'xxx' file*,或者grep 'xxx' *file


  • 在/var/log下,针对所有messages的log,搜索出包含关键字fail或者error的内容(忽略大小写)

grep-i-E'fail|error'/var/log/messages*

*注:-E代表扩展正则,通常情况下有如下5种扩展:

  • +:重复1次或者多次前面的字符,比如grep -E 'ab+c' file,表示在file中搜索包括1个a,多个b,并且跟上1个c的内容

  • ?:重复0次或者1次前面的字符,比如grep -E 'ab?c' file, 表示在file中搜索包括1个a,0个b或者1个b,并且跟上1个c的内容

  • |:用“或”的方式查找多个符合的字符串,比如grep -E 'fail|error' file

  • ():作为某个特定组合,比如说grep -E 'level=(fail|error)' file,表示在file中查找包括level=fail或者level=error的内容。如果去掉括号grep -E 'level=fail|error' file,代表查找匹配level=fail或者一行中单独匹配error的内容

  • {m,n}/{m,}/{,n}/{n}:表示重复m到n次(闭区间)/大于等于m次/小于等于n次/n次,在不用-E参数时,所有这部分花括号用法得两侧加反斜线:\{m,n\}


  • 在/var/log/secure*文件中,统计出最近通过ssh访问本服务器的ip以及端口信息

首先,如果简单查看/var/log/secure文件,可以发现根据关键字"Accepted password for root from"可以获取到粗略信息如下:

Linux文件处理三剑客之grep但如果只是想获取到访问本服务器的ip以及端口信息(ip与端口不相同),此时就需要进行正则匹配,同时将匹配的内容给输出来,而不显示行中其它信息:

grep'Acceptedpasswordforrootfrom'secure*|grep-o'[0-9\.]*port[0-9]*'

Linux文件处理三剑客之grep

*注:-o是仅仅将匹配的内容显示出来(而不显示整行)。通过-o加正则的方式,可以获取出被grep匹配到的内容。


  • 在当前文件夹以及子文件夹下搜索内容包括'error'的信息

有时候系统会将过期日志新建一个子文件夹,并remove到该文件夹下去,如果某天用户希望找到当前文件夹以及子文件夹下的文件内容包括'error'的相关信息,可以通过-r参数来实现:

grep-r'error'./

*注:如果执行grep -r 'error' ./*.log,仅仅代表在当前目录下*.log文件中搜索'error'关键字的行


  • 取出Oracle的ddl中,普通索引或者unique索引的列名中包括'#'的相关行?(假设索引定义都在一行)

首先,Oracle的ddl信息如下:

Linux文件处理三剑客之grep

尝试一:grep -E 'CREATE INDEX|CREATE UNIQUE INDEX' ora_ddl.sql | grep '#'

分析,该尝试可能存在问题,如果索引名带'#',也会搜索出来

尝试二:grep 'CREATE INDEX|CREATE UNIQUE INDEX' ora_ddl.sql -E | grep -P ‘\(.+?\#.+?\)’

分析,上述语句首先将索引或者unique索引行搜索出,再通过-P的perl正则,对索引定义的括号"()"内字段名进行匹配,从而准确匹配出索引列中包括'#'的内容

尝试三:grep -P 'CREATE\s+(UNIQUE\s+){0,1}INDEX.+?\(.+?\#.*?\)' ora_ddl.sql

分析,上述语句通过一次grep,直接准确匹配出索引或者unique索引字段中包括'#'的内容

*注:perl正则匹配中

  • . 代表任意字符

  • \s代表空格或者制表符

  • ()中内容代表某个整体

  • +代表匹配一次或者多次

  • *代表匹配0次或者多次

  • .+?代表匹配到最近的对象(非贪婪)

  • {1,5}代表匹配1-5次(非1次跟5次,而是1次,2次,3次…5次)


总结

grep命令用来在文件中搜索匹配的内容,既可以在当前文件夹搜索,也可以在当前文件夹以及子文件夹搜索。既可以搜索一个文件,也可以搜索多个文件。grep提供了多种搜索的方式,既可以忽略大小写,也可以全词检索,还可以使用普通正则或者扩展正则再或者perl的正则。并且在输出结果的时候,既可以输出匹配的内容/文件名,也可以输出对应的行号或者匹配内容的总个数,还可以输出匹配内容的前后多少行,或者干脆输出不匹配的部分。在使用正则进行匹配的时候,常见的shell正则grep都能支持,如果有进一步的正则扩展,请使用-E参数。但请注意grep没办法对某一列的内容进行匹配而后输出,除非使用一个很长的正则一直匹配到该列内容。所以很多时候grep的搜索会有不精确性,需要用户在搜索的基础上进行二次过滤,或者使用更加准确的搜索pattern。

总之,grep是Linux上强大的文件检索工具,用户几乎可以使用grep一个命令检索到所需要的各种信息,当然,很多时候还需要使用管道进行多重grep。

延伸 · 阅读

精彩推荐