简介

grep命令,用于在一个文本文件中或者从STDIN中,根据用户给出的模式(pattern)过滤出所需要的信息。

grep以及三剑客中的另外两个工具sed和awk都是基于行处理的,它们会一行行读入数据,处理完一行之后再处理下一行。

简要语法格式如下。

  1. grep [OPTIONS] PATTERN [FILE...]
  2. grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]

默认情况下,grep读取的行数据,如果整行内容中的某部分和模式相匹配的话,就会将该行内容输出。

例如,在/etc/passwd文件中找出包含“root”字符串的行。

该示例中的“root”字符串,就是模式。模式的强大之处在于它支持正则表达式。

例如,在/etc/passwd文件中找出以“root”或者“zwl”字符串开头的行。

该示例中的模式的书写就是字符串结合了正则表达式,而“^(|”字符就是正则表达式的元字符。

环境

CentOS 7.5

GNU grep 2.20

常用选项

首先我们先回顾一下语法。

  1. grep [OPTIONS] PATTERN [FILE...]
  2. grep [OPTIONS] [-e PATTERN | -f FILE] [FILE...]

第一种语法是比较常用的语法,选项可以省略,如果结合管道的话,那么文件也可以省略了。上面2个示例就是使用了该种语法。

在第二种语法中,我们见到了-e和-f选项。

-e PATTERN, --regexp=PATTERN:该选项的作用在于可以指定多个模式来匹配或者当遇到模式是以“-”开始的时候起到一个保护作用。

指定多模式的语法类似如下。

  1. grep -e 'PATTERN1' -e 'PATTERN2' FILE

从FILE中读取第一行,然后首先和PATTERN1匹配,匹配成功则显示第一行并进入下一行匹配;不成功就和PATTERN2匹配,匹配成功则显示第一行并进入下一行匹配;均不成功就进入下一行匹配。以此类推。

  1. [root@C7 ~]# grep -e '^root' -e '^zwl' /etc/passwd

另外一个保护的功能,我暂不知是什么意思,有知道的朋友可以分享一下。

-f FILE, --file=FILE:表示模式不再在CLI中指定,而是将模式写入一个文件中,每行一个模式,然后通过-f选项读取包含模式的文件。

--help:查看帮助。罗列了大部分选项的简要描述,不过没包含元字符解释。

-V, --version:如果是向grep官方递交bug的时候,需要带上版本。

-G, --basic-regexp:将模式解释为基本正则表达式,这是grep的默认行为。

-E, --extended-regexp:将模式解释为扩展正则表达式。

-F, --fixed-strings:将模式解释为固定的字符串,即禁用正则。虽然失去了正则的功能,但是换来性能的极大提升,当遇到大文本文件的时候相当好用。

--color=auto:将被grep所匹配到的内容给予着色处理,就像上面的截图中所显示的,通过正则所匹配到的字符串会被着色。由于我使用的系统是CentOS 7,该系统上的grep启用了显示着色的别名,因此我们不使用该选项也可以显示颜色。

  1. alias egrep='egrep --color=auto'
  2. alias fgrep='fgrep --color=auto'
  3. alias grep='grep --color=auto'

然而在CentOS 6上默认是没有的,需要自行添加。

-i, --ignore-case:表示模式的匹配是忽略大小写的。

  1. [root@C7 ~]# cat grep.txt
  2. alongdidi
  3. ALONGdidi
  4. xiamen
  5. XiaMen
  6. [root@C7 ~]# grep 'xiamen\|alongdidi' grep.txt
  7. alongdidi
  8. xiamen
  9. [root@C7 ~]# grep -i 'xiamen\|alongdidi' grep.txt
  10. alongdidi
  11. ALONGdidi
  12. xiamen
  13. XiaMen

-v, --invert-match:表示反向匹配。默认是将匹配模式的行打印出来,而使用该选项的话,则是将不匹配的行打印出来。

  1. [root@C7 ~]# cat grep.txt
  2. alongdidi
  3. ALONGdidi
  4. xiamen
  5. XiaMen
  6. [root@C7 ~]# grep -iv 'xiamen' grep.txt
  7. alongdidi
  8. ALONGdidi

从这个示例中,我们也可以发现,--color=auto的着色,只会将模式所匹配到的内容进行着色,不匹配的不着色。

-o, --only-matching:表示仅打印出模式所匹配的字符,而不是将整行都打印出来。

  1. [root@C7 ~]# grep '^root' /etc/passwd
  2. root:x:::root:/root:/bin/bash
  3. [root@C7 ~]# grep -o '^root' /etc/passwd
  4. root

-o选项的模式匹配出来的字符串个数,不等同于文本文件中对应有那么多行匹配。

  1. [root@C7 ~]# grep 'root' /etc/passwd
  2. root:x:::root:/root:/bin/bash
  3. operator:x:::operator:/root:/sbin/nologin
  4. [root@C7 ~]# grep -o 'root' /etc/passwd
  5. root
  6. root
  7. root
  8. root

-n, --line-number:在显示出匹配的内容时,通过该选项,显示匹配模式的行在输入文件中的行号。

  1. [root@C7 ~]# grep -n 'xiamen' grep.txt
  2. :xiamen

-q, --quiet, --silent:静默模式,不会输出任何信息到STDOUT,即便遇到诸如文件不存在或者文件不可读的错误情况,也不会输出。匹配成功则返回0状态码,一般用于结合$?做判断。

-A NUM, --after-context=NUM:打印匹配到的文本所在行以及其后面NUM行,NUM是一个正整数。

-B NUM, --before-context=NUM:打印匹配到的文本所在行以及其前面NUM行。

-C NUM, -NUM, --context=NUM:打印匹配到的文本所在行以及其上下NUM行。

  1. [root@C7 ~]# cat grep.txt
  2. aaa
  3. bbb
  4. ccc
  5. zhongjian
  6. ddd
  7. eee
  8. fff
  9. [root@C7 ~]# grep -A 'zhongjian' grep.txt
  10. zhongjian
  11. ddd
  12. eee
  13. fff
  14. [root@C7 ~]# grep -B 'zhongjian' grep.txt
  15. aaa
  16. bbb
  17. ccc
  18. zhongjian
  19. [root@C7 ~]# grep -C 'zhongjian' grep.txt
  20. aaa
  21. bbb
  22. ccc
  23. zhongjian
  24. ddd
  25. eee
  26. fff

常用选项就说到这里,基本可以满足日常需求,grep的真正强大之处在于与正则表达式的结合。

正则表达式

正则表达式可使用在grep的匹配模式当中,它由多个元字符所组成,用于匹配出用户所期望的特定的字符串。

因此正则表达式的重点就在于元字符。

元字符

字符匹配

.:匹配任意单个字符。

[]:匹配任意范围内的单个字符,这里的范围,支持类似glob的机制(详见man 7 glob),支持字符类(character classes),如下。

  [:alnum:]:字母和数字。

  [:alpha:]:字母。

  [:digit:]:数字。

  [:lower:]:小写字母。

  [:upper:]:大写字母。

  [:space:]:空白字符,例如空格或者制表符。

  [:punct:]:标点符号。

  [:graph:]:非空字符。

  等等。

[^]:匹配任意范围外的单个字符。

次数匹配

*:匹配前面的字符任意次(0次、1次或者多次)。一般是结合“.”使用,例如“.*”表示匹配任意长度的任意字符,即等同于glob中的通配符“*”。

?:匹配前面的字符0次或1次,即前面的字符可有可无。

+:匹配前面的字符1次或多次,即前面的字符至少出现1次。

{m}:匹配前面的字符m次。

  {m,n}:匹配前面的字符,至少m次,至多n次。

  {0,n}或者{,n}:匹配前面的字符,至多n次。

  {m,}:匹配前面的字符,至少m次。

位置锚定

^:锚定行首,表示模式必须出现在行的最左侧。

$:锚定行尾,表示模式必须出现在行的最右侧。

^PATTERN$:整行锚定,表示模式必须刚好匹配整行的内容。

  ^$:匹配空行。

\<或者\b:锚定词首。

\>或者\b:锚定词尾。

一般是不使用\b,因为它不能明确表示词首或者词尾。

\<PATTERN\>:整词锚定。

分组及引用

():表示分组,可用于将某个模式或字符串包裹,用于次数匹配,例如“xy+”和“(xy)+”的区别。不过主要的作用是用于后向引用。

\n:表示引用,n是一个正整数,表示引用第几个分组的内容。例如“^(root).*\1$”。分组之后可以不引用,而如果涉及了引用,那么必定存在分组。

基本正则与扩展正则

正则表达式又分为基本正则表达式(BRE)和扩展正则表达式(ERE)。

它们的区别在于元字符支持的不同。ERE在包含了BRE的元字符的基础上又进行了扩展。

BRE的元字符:.、[]、[^]、*、^、$、\b、\<、\>、\n(引用)。

ERE的元字符:?、+、{}、()、|。

对于Linux中的GNU grep工具来说,两种正则是都支持的,区别在于元字符的书写方式不同。

默认情况下,grep命令支持的是BRE,因此在书写BRE元字符的时候不改变,在书写ERE元字符的时候,需要在元字符前面加上转义字符“\”。

如果通过-E选项开启支持ERE的话,那么在书写BRE和ERE元字符的时候,都不需要改变。如下所示。

  1. # grep "^\(root\)\?" /PATH/TO/FILE
  2. # grep -E "^(root)?" /PATH/TO/FILE

因此可以每次都使用-E选项来书写模式。

在开启-E选项支持ERE的前提下,如果想要匹配ERE的元字符自身,例如想匹配一个问号“?”,那么就需要加上转义“\?”。

仅仅解释每个元字符的作用,不好理解,通过一些示例来体会一下。

示例

1、找出/etc/passwd中不以“/bin/bash”结尾的行。

  1. [root@C7 ~]# grep -v "/bin/bash$" /etc/passwd
  2. bin:x:::bin:/bin:/sbin/nologin
  3. daemon:x:::daemon:/sbin:/sbin/nologin
  4. adm:x:::adm:/var/adm:/sbin/nologin
  5. lp:x:::lp:/var/spool/lpd:/sbin/nologin
  6. sync:x:::sync:/sbin:/bin/sync
  7. ...

2、找出/etc/passwd中含有两位数或三位数作为字段信息的行。

  1. [root@C7 ~]# grep -E "\<[[:digit:]]{2,3}\>" /etc/passwd
  2. mail:x:::mail:/var/spool/mail:/sbin/nologin
  3. operator:x:::operator:/root:/sbin/nologin
  4. games:x:::games:/usr/games:/sbin/nologin
  5. ftp:x:::FTP User:/var/ftp:/sbin/nologin
  6. nobody:x:::Nobody:/:/sbin/nologin
  7. ...

3、找出/etc/rc.d/init.d/functions中,至少一个空白开头并且后面跟着至少一个非空白字符的行。

  1. [root@C7 ~]# grep -E "^[[:space:]]+[^[:space:]]+" /etc/rc.d/init.d/functions

4、找出netstat -atn命令结果中以LISTEN后跟任意个空白字符的行。

  1. [root@C7 ~]# netstat -atn | grep "LISTEN[[:space:]]*"
  2. tcp 0.0.0.0: 0.0.0.0:* LISTEN
  3. tcp 192.168.122.1: 0.0.0.0:* LISTEN
  4. tcp 0.0.0.0: 0.0.0.0:* LISTEN
  5. tcp 127.0.0.1: 0.0.0.0:* LISTEN
  6. tcp 127.0.0.1: 0.0.0.0:* LISTEN
  7. tcp6 ::: :::* LISTEN
  8. tcp6 ::: :::* LISTEN
  9. tcp6 ::: :::* LISTEN
  10. tcp6 ::: :::* LISTEN

5、找出示例文件中,前后都包like或者love的行。

  1. [root@C7 ~]# cat test.txt
  2. He likes his lover.
  3. He loves his lover.
  4. She likes her liker.
  5. She lovers her liker.
  6. [root@C7 ~]# grep -E "(l..e).*\1" test.txt
  7. He loves his lover.
  8. She likes her liker.

6、找出/proc/meminfo文件中,所有以Mem或者mem开头的行。

  1. [root@C7 ~]# grep -E '^[Mm]em' /proc/meminfo
  2. MemTotal: kB
  3. MemFree: kB
  4. MemAvailable: kB
  5. [root@C7 ~]# grep -E '^(M|m)em' /proc/meminfo
  6. MemTotal: kB
  7. MemFree: kB
  8. MemAvailable: kB

7、查找/etc/passwd中root、postfix和haimianbb用户的相关信息。

  1. [root@C7 ~]# grep -E "^(root|postfix|haimianbb)\>" /etc/passwd
  2. root:x:::root:/root:/bin/bash
  3. postfix:x::::/var/spool/postfix:/sbin/nologin
  4. haimianbb:x::::/home/haimianbb:/bin/bash

8、找出/etc/init.d/functions文件中的函数名(可以含括号)。

留意函数名的特征(数字字母下划线)。留意-o选项的作用。启用ERE之后,()有分组的含义,因此如果模式要匹配出字面意义上的()就需要使用转义“\(\)”。

  1. [root@C7 ~]# grep -Eo "[_[:alnum:]]+\(\)" /etc/init.d/functions
  2. checkpid()
  3. __kill_pids_term_kill_checkpids()
  4. __kill_pids_term_kill()
  5. __pids_var_run()
  6. __pids_pidof()
  7. daemon()
  8. ...

9、通过grep实现basename命令的功能。

  1. [root@C7 ~]# basename /etc/init.d/functions
  2. functions
  3. [root@C7 ~]# basename /etc/init.d/functions/
  4. functions
  5. [root@C7 ~]# echo "/etc/init.d/functions" | grep -Eo "[^/]+/?$" | grep -Eo "[[:alnum:]]+"
  6. functions
  7. [root@C7 ~]# echo "/etc/init.d/functions/" | grep -Eo "[^/]+/?$" | grep -Eo "[[:alnum:]]+"
  8. functions

10、通过grep实现dirname命令的功能。

不知道如何实现,期待各位博友的分享。

11、找出ifconfig命令结果中,以独立单词形式存在的1000以内的数字。

  1. [root@C7 ~]# ifconfig | grep -E "\<([1-9]|[1-9][0-9]|[1-2][0-9][0-9])\>"
  2. [root@C7 ~]# ifconfig | grep -Eo "\<([1-9]|[1-9][0-9]|[1-2][0-9][0-9])\>"

12、找出ifconfig命令结果中的IP地址。

这种判断方式比较鲁莽,并没有针对IP地址的特性,例如每个字节的最大十进制数是255。

  1. [root@C7 ~]# ifconfig | grep -Eo "[[:digit:]]{,3}(\.[[:digit:]]{,3}){3}"
  2. 192.168.17.7
  3. 255.255.255.0
  4. 192.168.17.255
  5. 127.0.0.1
  6. 255.0.0.0
  7. 192.168.122.1
  8. 255.255.255.0
  9. 192.168.122.255

13、查找/etc/passwd中,用户名等同于shell名称的用户信息。

  1. [root@C7 ~]# grep -E "(^[[:alnum:]-]+\>).*\1$" /etc/passwd
  2. sync:x:::sync:/sbin:/bin/sync
  3. shutdown:x:::shutdown:/sbin:/sbin/shutdown
  4. halt:x:::halt:/sbin:/sbin/halt
  5. bash:x::::/home/bash:/bin/bash
  6. nologin:x::::/home/nologin:/sbin/nologin

Linux文本处理三剑客之grep的更多相关文章

  1. Linux文本处理三剑客之grep及正则表达式详解

    Linux文本处理三剑客之grep及正则表达式详解 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.Linux文本处理三剑客概述 grep: 全称:"Global se ...

  2. Linux文本处理三剑客之——grep

    一Linux文本处理三剑客之——grep Linux文本处理三剑客都支持正则表达式 grep :文本过滤( 模式:pattern) 工具,包括grep, egrep, fgrep (不支持正则表达式) ...

  3. Linux 文本处理三剑客之grep

    文本处理都要使用正则表达式,正则表达式有: 基本正则表达式:grep或者egrep -G 扩展正则表达式:egreo或者grep -E Linux 文本处理三剑客: sed:stream editor ...

  4. linux文本处理三剑客之 grep

    文本处理无非是对文本内容做查看.修改等操作.Linux三剑客: grep.sed 和 awk 命令. 处理文本内容,用 Vim 编辑器不是很好吗?Vim 允许我们使用键盘.鼠标来对文本内容进行交互性地 ...

  5. 二、LINUX文本处理三剑客之grep

    1. grep一般格式:grep [选项] 基本正则表达式 [文件],其中基本正则表达式需要用引号引起来 引号引起来的作用:a.防止被误解为shell命令,b.可以用来查找多个单词组成的字符串 gre ...

  6. Linux文本处理三剑客之sed

    推荐新手阅读[酷壳]或[骏马金龙]开篇的教程作为入门.骏马兄后面的文章以及官方英文文档较难. [酷壳]:https://coolshell.cn/articles/9104.html [骏马金龙-博客 ...

  7. 关于Linux文本处理“三剑客”的一些小操作。

    Linux文本处理“三剑客”,即grep.sed.awk,这是Linux中最核心 的3个命令. 一.首先做个简单的介绍: 1.awk:linux三剑客老大,过滤,输出内容,一门语言.NR代表行号. 2 ...

  8. 文本处理三剑客之 grep

    grep简介 grep(Global search REgular expression and Print out the line)是Linux上的文本处理三剑客之一,另外两个是sed和awk. ...

  9. shell 文本处理三剑客之 grep 和 egrep

    shell 三剑客之 grep 命令语法格式 grep 参数 案例 显示file中有python的行 grep python file 显示没有python的行,不忽略大小写 grep -v pyth ...

随机推荐

  1. 实例详析ImageView的adjustViewBonds和scaleType

    android:adjustViewBounds是否保持宽高比.需要与maxWidth.MaxHeight一起使用,否则单独使用没有效果. 设置View的最大高度,单独使用无效,需要与setAdjus ...

  2. NFS配置不当导致的那些事儿

    NFS(Network File System):是FreeBSD支持的文件系统中的一种,它允许网络中的计算机之间通过TCP/IP网络共享资源: NFS配置:(声明:以下NFS实验是在RedHat7上 ...

  3. Dubbo重试次数

    服务超时后重试次数[retries],不包含第一次调用,0代表不重试 *我们应该在幂等方法上设置重试次数[查询.删除.修改],在非幂等方法上禁止设置重试次数. ★幂等:指多次运行方法所产生的最终效果是 ...

  4. GitHub:Awesome-Hacking(黑客技能列表-恶意代码)

    0 初衷 GitHub这一份黑客技能列表很不错,包含了多个方向的安全.但目前我关注只有逆向工程与恶意代码,所以其他的被暂时略过. 虽然很感谢作者的辛勤付出,但并不打算复制粘贴全套转载.逐条整理是为了从 ...

  5. Difference between plt.draw() and plt.show() in matplotlib

    Difference between plt.draw() and plt.show() in matplotlib down voteaccepted plt.show() will display ...

  6. python通过操作windows系统注册表方式修改环境变量

    #coding=utf8 import os import sys from subprocess import check_call if sys.hexversion > 0x0300000 ...

  7. java项目中oracle配置说明

    配置信息: #oracle database settings jdbc.url::orcl jdbc.username=cognos_data jdbc.password=cognos_data j ...

  8. bzoj 1803: Spoj1487 Query on a tree III(主席树)

    题意 你被给定一棵带点权的n个点的有根数,点从1到n编号. 定义查询 query(x,k): 寻找以x为根的k大点的编号(从小到大排序第k个点) 假设没有两个相同的点权. 输入格式: 第一行为整数n, ...

  9. javaScript——原型继承四步曲

    <script> //js模拟类的创建以及继承 //第一步:创建父类 function Parent(name){ this.name = name; } //给父类添加属性方法 Pare ...

  10. 单个 LINQ to Entities 查询中的两个结构上不兼容的初始化过程中出现类型“XXXX”

    最近在做一个报表的时候,用EF使用了Contact方法,但是程式运行一直出错.最近终于找到原因了,写下来提醒下自己.好了,进入正题: 现在我举个栗子,目前数据库中有ParentStudent表和Sub ...