zoukankan      html  css  js  c++  java
  • Linux grep命令详解

    grep命令详解

    grep命令用于在文本中查找指定的字符串。可以把grep理解为字符查找工具,grep是一个可以利用正则表达式进行全局搜索的工具,并将搜索出来的行打印出来。当然,不使用正则表达式也可以使用grep,但是grep与正则结合在一起,功能会更加强大。

    我们先来看一个简单的例子,认识一下grep,我们从一个文本文件中找出包含test字符串的行:

    [root@localhost shell]# cat testgrep 
    zsy test
    zsythink
    
    www.zsythink.net
    TEST 123
    Zsy's articles
    grep Grep
    abc
    abc123abc
    123zsy123
    [root@localhost shell]# grep "test" testgrep 
    zsy test

    上例中表示使用grep命令,在文件中搜索包含"test"字符串的行。并将包含"test"字符串的行打印出来。于是,文件的第一行被打印出来,默认情况下,grep是区分大小写的,所有TEST没有被打印。

    如果我们在搜索字符串的时候,想要不区分大小写,可以通过使用 -i 参数,即可在搜索时不区分大小写,示例如下:

    [root@localhost shell]# grep -i "test" testgrep 
    zsy test
    TEST 123

    由于testgrep文件行数较少,所有可以数过来时第一行和第五行包含test字符串,但是如果文件很大,成千上万行。想要指定文本哪行包含test字符串,我们可以使用 -n 参数。表示显示打印出的行在文本中的行号:

    [root@localhost shell]# grep -i -n "test" testgrep 
    1:zsy test
    5:TEST 123

    在centos6系统中,我们使用grep在文本中搜索的行被打印出来,但是匹配到的关键字没有以高亮度显示,如果我们想要高亮度显示匹配到的关键字。我们可以使用 --color选项,使用 --color 和使用 --color=auto的效果相同。在centos7中,系统默认为grep命令配置了别名,不用显式指定 --color 选项。默认高亮显示被匹配到的关键字,可以通过alais命令查看别名:

    [root@localhost shell]# alias
    alias cp='cp -i'
    alias egrep='egrep --color=auto'
    alias fgrep='fgrep --color=auto'
    alias grep='grep --color=auto'
    alias l.='ls -d .* --color=auto'
    alias ll='ls -l --color=auto'
    alias ls='ls --color=auto'
    alias mv='mv -i'
    alias rm='rm -i'

     在testgrep文本中,一共有两行包含了 test 字符串。如果我们不关心包含test行的内容,只想知道有多少行包含test字符串,这时候我们可以使用 -c 参数。

    [root@localhost shell]# grep -i "test" testgrep 
    zsy test
    TEST 123
    [root@localhost shell]# grep -i -c "test" testgrep 
    2

    以上的示例中,包含关键词的行都被打印出来了,打印的是整行内容。如果只想看到被匹配的关键字,而不需要整行的内容。我们可以使用 -o 参数来实现只打印匹配到的关键字,而不打印整行,示例如下:

    [root@localhost shell]# grep -i -o "test" testgrep 
    test
    TEST

     需要注意的是,-o参数会把每个匹配到的关键字都单独在一行内进行输出,示例如下:

    [root@localhost shell]# grep -i "123" testgrep 
    TEST 123
    abc123abc
    123zsy123
    [root@localhost shell]# grep -i -o "123" testgrep 
    123
    123
    123
    123
    [root@localhost shell]# grep -i -n -o "123" testgrep 
    5:123
    9:123
    10:123
    10:123

    如上所示:当没有使用 -o 选项时,包含123字符串的行都被打印出来。当同一行包含多个123时,所在行会被打印出来。对应的关键字也会高亮显示。当使用了 -o 选项时,每个匹配到的关键字都会被单独打印到一行中去。在上例中,第三个和第四个123都是属于第十行的文本。

    在我们使用grep命令搜索文本时,往往有这种需求。在找到对应的关键字时,同时需要显示关键字附近的信息。我们通过一个场景来了解一下。我们在一个以下一个文本中找出年龄为18的人。

    [root@localhost shell]# cat testgrep1 
    姓名:小泽老师
    年龄:18
    评分:98
    
    姓名:苍老师
    年龄:32
    评分:99
    
    姓名:波多老师
    年龄:18
    评价:95
    [root@localhost shell]# grep "年龄:18" testgrep1 
    年龄:18
    年龄:18

    上例中只是匹配到了年龄,但是并不知道姓名,因为姓名和年龄并不在同一行。这时我们可以使用 -B选项,显示符合条件的行之前的行,B可以理解为before之意。示例如下:

    [root@localhost shell]# grep -B1 "年龄:18" testgrep1 
    姓名:小泽老师
    年龄:18
    --
    姓名:波多老师
    年龄:18

     如上图所示,包含年龄18的行被输出了。同时符合条件的前一行也被输出了,上例中的 -B1选项就是表示显示符合条件的行同时还显示之前的一行。同样的 -B5 代表显示之前的5行  -B3 代表显示之前的3行,-B选项后面必须跟数字,否则会报错。

    与 -B 选项对应的是 -A 选项 B有before之意,A有after之意。所以,-A表示显示符合条件行的同时,还要显示之后的行。

    介绍了 -A和-B选项。可以再看看 -C ,-C可以理解为 -A 和 -B 的结合。-C表示显示符合条件的行的同时,还要显示前后的行。如 -C1 表示打印符合条件行的同时,也打印出之前的一行和之后的一行。C有context(上下文之意)。示例如下:

    [root@dm shell]# grep -C1 "年龄:18" testgrep1 
    姓名:小泽老师
    年龄:18
    评分:98
    --
    姓名:波多老师
    年龄:18
    评价:95

    这样,就可以看到年龄18岁的人所有信息了。

    有的时候,我们需要精准匹配,上述的方法显然无法满足。示例如下:

    [root@dm shell]# cat testgrep
    zsy test
    zsythink
    
    www.zsythink.net
    TEST 123
    Zsy's articles
    grep Grep
    abc
    abc123abc
    123zsy123
    [root@dm shell]# grep "zsy" testgrep
    zsy test
    zsythink
    www.zsythink.net
    123zsy123

    我们在文本中搜索zsy字符串的时候,zsy zsythink 123zsy123所在的行都被匹配到了。因为zsythink中包含了zsy,所以也被匹配到了。但是如果想要精确匹配zsy字符串的时候,上例中的方法就无法做到了。所谓精确匹配,就是zsy作为单独一个词存在,而不是存在于某个字符串中。 那么这种需求我们该如何实现呢,使用 -w 选项可以满足我们的需求。示例如下:

    [root@dm shell]# grep "zsy" testgrep
    zsy test
    zsythink
    www.zsythink.net
    123zsy123
    [root@dm shell]# grep -w "zsy" testgrep
    zsy test

    如上例所示,使用了 -w 选项之后,只有zsy作为一个单独的单词而存在的时候,才会被匹配到。zsy包含于某个字符串时,不会被匹配到。这就是所谓的精准匹配, -w有word之意。表示搜索一个字符串作为一个独立的单词时才会被匹配到。

    有些时候,我们需要反向查找。比如查找不包含某些字符串的行,这个时候,我们需要用到 -v 选项。示例如下:

    [root@dm shell]# cat testgrep
    zsy test
    zsythink
    
    www.zsythink.net
    TEST 123
    Zsy's articles
    grep Grep
    abc
    abc123abc
    123zsy123
    [root@dm shell]# grep -i -v "zsy" testgrep
    
    TEST 123
    grep Grep
    abc
    abc123abc

    上例中表示查找不包含zsy字符串的行。

    有的时候,我们可能需要从多个目标中匹配。什么意思呢,我们通过示例来看:

    [root@dm shell]# grep -e "abc" -e "test" testgrep
    zsy test
    abc
    abc123abc

    上例中,我们同时在文本中搜索abc字符串和test字符串。包含这两个字符串的任意一个都会被打印出来,就像上面的示例一样。使用 -e 选项可以同时匹配多个目标,多个目标之间存在或联系。即匹配其中任意一个都算匹配成功。

    在写脚本时,有时只想利用grep判断文本中是否存在某个字符串。只关心有没有匹配到,而不关心匹配到的内容。只关心有或没有,这时,我们就可以使用grep的静默模式。示例如下:

    [root@dm shell]# grep -q "test" testgrep
    [root@dm shell]# echo $?
    0
    [root@dm shell]# grep -q "ttttttt" testgrep
    [root@dm shell]# echo $?
    1

    当使用 -q 选项时,表示使用grep静默模式,静默模式下grep不会输出任何信息。无论是否匹配到指定的字符串,都不会输出任何信息。所以,我们需要配合 echo $? 命令,查看命令的执行状态。如果返回值为0,证明上一条grep命令匹配到了指定的字符串。如果返回为1,证明上一条grep命令没有匹配到指定的字符串。

    在开头我们说了,grep可以利用正则表达式进行搜索。但是之前的举例中,grep都没有使用正则表达式。只是纯粹的查找一些字符串,这次我们使用grep命令配合正则表达式,来查找我们想要的目标。比如,我们想找到一个文本中的合法邮箱。

    [root@dm shell]# cat testgrep2
    sdasfas
    zsythink@yeah.net
    asdsadfasffsfsfs@
    @dwdaj
    [root@dm shell]# grep -E "^([[:alnum:]]{6,18})@([[:alnum:]]{1,20}).(com(.cn)?|org|edu|net|mil|gov|info)$" testgrep2 
    zsythink@yeah.net

    上例中我们使用了扩展的正则表达式,而不是基础的正则表达式。所有,上述命令中,我们使用了 -E 选项。

    在使用了 -E 选项时,grep才支持扩展正则表达式,不适用 -E 选项时,grep默认只支持基本正则表达式。

    另:不同的开发语言中,正则表达式的规则可能略有不同。我们使用grep时,可以使用 -P 选项,指明使用perl兼容的正则表达式。示例如下:

    [root@dm shell]# grep -P "[a-zA-Z0-9_-]+@[a-zA-Z0-9_-]+(.[a-zA-Z0-9_-]+)+" testgrep2
    zsythink@yeah.net

    grep的常用选项已经总结完了。其实,除了grep命令,还有egrep和fgrep命令

    grep : 支持基本正则表达式

    egrep : 支持扩展正则表达式,相当于grep -E

    fgrep : 不支持正则表达式,只能匹配写死的字符串。但是速度快,效率高,fastgrep

    总结

    grep的常用选项总结如下:

    --color=auto或者--color:对匹配的文本着色显示

    -i : 搜索的时候忽略大小写

    -n : 显示结果所在行号

    -c : 统计匹配到的行数,注意时匹配到的总行数,不是匹配到的次数

    -o : 只显示符合条件的字符串,但是不整行显示,每个符合条件的字符串单独显示一行

    -v : 输出不带关键字的行(反向查询,反向匹配)

    -w : 匹配整个单词,如果是字符串中包含这个单词,则不做匹配

    -Ax : 在输出的时候包含结果所在行之后的指定行数,这里指之后的x行

    -Bx : 在输出的时候包含结果所在行之前的指定行数,这里指之后的前行

    -Cx : 在输出的时候包含结果所在行之前和之后的指定行数,这里指之前和之后的x行

    -e : 实现多个选项的匹配,逻辑 or 关系

    -q : 静默模式,不输出任何信息。然后使用echo $?查看是否匹配到,0表示匹配到,1表示没有匹配到。

    -P : 表示使用兼容perl的正则引擎

    -E : 使用扩展正则表达式,而不是基本正则表达式,相对于使用egrep

  • 相关阅读:
    [LeetCode]52. Bulls and Cows猜数字游戏
    [LeetCode]51. Ismorphic Strings同构字符串
    [LeetCode]50. Valid Anagram有效变位词
    [LettCode]49. Valid Sudoku有效数独
    [LeetCode]48. Word Pattern匹配模式
    Ubuntu 14.04中安装Sublime Text 3并使用SublimeClang插件
    [LeetCode]47. Integer to English Words整数的读法
    六度空间
    Saving James Bond
    列出图的连通集
  • 原文地址:https://www.cnblogs.com/jkin/p/11356510.html
Copyright © 2011-2022 走看看