首页 > 代码库 > Linux文本处理"三剑客"--grep

Linux文本处理"三剑客"--grep

稍微接触过linux都会知道有三个非常强大文本处理工具,那就是grep、sed和awk,想必都有听说过吧。


Linux文本处理三剑客:

  grep, egrep, fgrep:文本过滤工具(模式:pattern);

    grep:基本正则表达式,支持-E,-F

    egrep:扩展正则表达式, 支持-G,-F

    fgrep:不支持正则表达式,

  sed:stream editor, 流编辑器;文本编辑工具;

  awk:Linux上的实现为gawk,文本报告生成器(格式化文本);


以上三款工具都支持正则表达式


正则表达式:Regual Expression, REGEXP

  由一类特殊字符及文本字符所编写的模式,其中有些字符不表示其字面意义,而是用于表示控制或通配的功能;

    分两类:

      基本正则表达式:BRE

      扩展正则表达式:ERE


grep: Global search REgular expression and Print out the line.

 作用:文本搜索工具,根据用户指定的“模式(过滤条件)”对目标文本逐行进行匹配检查;打印匹配到的行

  模式:由正则表达式的元字符及文本字符所编写出的过滤条件


  格式:

    grep  [OPTIONS]  PATTERN  [FILE...]

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


  选项(OPTIONS):

    --color=auto:对匹配到的文本着色后高亮显示;(在centos7中管理员alias中已定义,centos6中没有定义)

      [root@test7_1 ~]# alias

      alias grep=‘grep --color=auto‘


    -i:ignorecase,忽略字符的大小写

      [root@centos7 ~]# grep -i "uuid" /etc/fstab 

      UUID=48604746-41c1-41df-aaf1-f3588bfd3edc  /  xfs  defaults  0 0


    -o:仅显示匹配到的字符串本身

      [root@centos7 ~]# grep -o "UUID" /etc/fstab

      UUID


    -v, --invert-match:显示不能被模式匹配到的行;取反的意思

      [root@test7_1 ~]# grep -v "UUID" /etc/fstab


    -n:显示模式匹配到内容的行号

    -E:支持使用扩展的正则表达式元字符

    -q, --quiet, --silent:静默模式,即不输出任何信息

    -A #:after, 后#行

      [root@test7_1 ~]# grep -A 1 "root" /etc/passwd

       root:x:0:0:root:/root:/bin/bash

       bin:x:1:1:bin:/bin:/sbin/nologin

    -B #:before,前#行

      [root@test7_1 ~]# grep -B 1 "^bin" /etc/passwd

       root:x:0:0:root:/root:/bin/bash

       bin:x:1:1:bin:/bin:/sbin/nologin

    -C #:context,前后各#行

     [root@test7_1 ~]# grep -C 1 "^bin" /etc/passwd

       root:x:0:0:root:/root:/bin/bash

       bin:x:1:1:bin:/bin:/sbin/nologin

       daemon:x:2:2:daemon:/sbin:/sbin/nologin

    

基本正则表达式元字符:

  字符匹配:

    . :匹配任意单个字符;

      [root@centos7 sh]# grep "[[:punct:]]." issue 

      \S

    []:匹配指定范围内的任意单个字符;

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


    [[:upper:]]:所有大写字母

    [[:lower:]]:所有小写字母

    [[:alpha:]]:所有字母

    [[:digit:]]:所有数字

    [[:alnum:]]:所有的字母和数字

    [[:punct:]]:匹配标点符号

    [[:space:]]:匹配空白字符

    注:正则表达式中的范围匹配是区分大小写


 匹配次数:

    用在要指定其出现的次数的字符的后面,用于限制其前面字符出现的次数;默认工作于贪婪模式


    *:匹配其前面的字符任意次;0,1,多次;

      例如:grep "x*y",会匹配下面多种情况

        abxy、aby、xxxxxy、yab      

    .*:匹配任意长度的任意字符

    \?:匹配其前面的字符0次或1次;即其前面的字符是可有可无的;

    \+:匹配其前面的字符1次或多次;即其面的字符要出现至少1次;

    \{m\}:匹配其前面的字符m次;

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

      \{0,n\}:至多n次

      \{m,\}:至少m次


  位置锚定:

    ^:行首锚定;用于模式的最左侧;

    $:行尾锚定;用于模式的最右侧;

    ^PATTERN$:用于PATTERN(root)来匹配整行;

      ^$:空白行;

      ^[[:space:]]*$:空行或包含空白字符的行;

    \< 或 \b:词首锚定,用于单词模式的左侧;

    \> 或 \b:词尾锚定,用于单词模式的右侧;

    \<PATTERN\>:匹配完整单词;

  

    单词:非特殊字符组成的连续字符(字符串)都称为单词;


  分组及引用:

    \(\):将一个或多个字符捆绑在一起,当作一个整体进行处理;

      例:\(xy\)*ab

    Note:分组括号中的模式匹配 到的内容会被正则表达式引擎自动记录于内部的变量中,这些变量为:

      \1:模式从左侧起,第一个左括号以及与之匹配的右括号之间的模式所匹配到的字符

      \2:模式从左侧起,第二个左括号以及与之匹配的右括号之间的模式所匹配到的字符

      \3:模式从左侧起,第三个左括号以及与之匹配的右括号之间的模式所匹配到的字符

      ...


    示例:

      He loves his lover.

      He likes his lover.

      She likes her liker.

      She loves her liker.

      [root@test7_1 ~]# grep  "\(l..e\).*\1"  lovers.txt

    

    后向引用:引用前面的分组括号中的模式所匹配到的字符;


上述讲的是grep命令使用及基本正则表达式使用方法,grep是支持正则表达式,可以在工作中结合使用。先来几道练习题

  1、显示/etc/passwd文件中不以/bin/bash结尾的行;

  2、找出/etc/passwd文件中的两位数或三位数;

  3、找出/etc/rc.d/rc.sysinit或/etc/grub2.cfg文件中,以至少一个空白字符开头,且后面非空白字符的行;

  4、找出"netstat -tan"命令的结果中以‘LISTEN‘后跟0、1或多个空白字符结尾的行;


  解答:

   1、[root@test7_1 ~]# grep -v "/bin/bash$" /etc/passwd

    2、[root@test7_1 ~]# grep "\<[0-9]\{2,3\}\>" /etc/passwd

    3、[root@test7_1 ~]# grep  "^[[:space:]]\+[^[:space:]]"  /etc/grub2.cfg

    4、[root@test7_1 ~]# netstat -tan | grep  "LISTEN[[:space:]]*$"


===========================================================================================


egrep

  支持扩展的正则表达式实现类似于grep文本过滤功能;grep -E


  格式:

    egrep [OPTIONS] PATTERN [FILE...]

  选项:

    -i, -o, -v, -q, -A, -B, -C

    -G:支持基本正则表达式

  

  扩展正则表达式的元字符:

    扩展正则比基本正则多了一个“或”匹配模式,而扩展正则表达式写法比基本正则表达式简单易看  


    字符匹配:

      .:任意单个字符

      []:指定范围内的任意单个字符

      [^]:指定范围外的任意单个字符


    次数匹配:

      *:任意次,0,1或多次;

      ?:0次或1次,其前的字符是可有可无的;

      +:其前字符至少1次;

      {m}:其前的字符m次;

      {m,n}:至少m次,至多n次; 

        {0,n}

        {m,}

    

    位置锚定:

      ^:行首锚定;

      $:行尾锚定;

      \<, \b:词首锚定;

      \>, \b:词尾锚定;

  

    分组及引用:

      ():分组;括号内的模式匹配到的字符会被记录于正则表达式引擎的内部变量中;

      后向引用:\1, \2, ...


    或:

      a|b:a或者b;

        C|cat:C或cat

       (c|C)at:cat或Cat


练习:

  1、找出/proc/meminfo文件中,所有以大写或小写S开头的行;至少有三种实现方式;

  2、显示当前系统上root、centos或user1用户的相关信息;

  3、找出/etc/rc.d/init.d/functions文件中某单词后面跟一个小括号的行

  4、使用echo命令输出一绝对路径,使用egrep取出基名;

    /var/log/messages取出其路径名;类似于对其执行dirname命令的结果;

  5、找出ifconfig命令结果中的1-255之间的数值;

  6、找出ifconfig命令结果中的IP地址;

  7、添加用户bash, testbash, basher以及nologin(其shell为/sbin/nologin);而后找出/etc/passwd文件中用户名同shell名的行;


解:

  1、

    [root@centos7 sh]# grep -i ‘^s‘ /proc/meminfo

    [root@centos7 sh]# grep ‘^[sS]‘ /proc/meminfo

    [root@centos7 sh]# egrep ‘^(s|S)‘ /proc/meminfo

  2、首先需要创建用户

    [root@centos7 sh]# grep -E "^(root|centos|user1)\>" /etc/passwd

  3、[root@centos7 sh]# grep -E -o "[_[:alnum:]]+\(\)"  /etc/rc.d/init.d/functions

  4、[root@centos7 sh]# echo /etc/sysconfig/ | grep -E -o "[^/]+/?$"

   [root@centos7 sh]# echo /var/log/messages | grep -E -o "^[/]?.*/"

  5、[root@centos7 sh]# ifconfig | grep -E -o "\<([1-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\>"

  6、

  7、[root@centos7 sh]# grep -E "^([^:]+\>).*\1$" /etc/passwd

   


fgrep:不支持正则表达式元字符;

  当无需要用到元字符去编写模式时,使用fgrep必能更好、速度更快;




文本查看及处理工具:wc, cut, sort, uniq, diff, patch



wc:word count(统计文本字数)

  格式:

    wc  [OPTION]...  [FILE]...

  选项:

    -l: lines(行数)

    -w:words(单词:所有连续的字母都叫单词)

    -c: bytes(字节数:大小)

  示例:

    [root@test7_1 ~]# wc anaconda-ks.cfg

    43  101 1143 anaconda-ks.cfg

      解:43行、101单词、1143字符大小



cut:分隔截取指定内容

  格式:

    cut OPTION... [FILE]...

  选项:

    -b:以字节为单位进行分割。这些字节位置将忽略多字节字符边界,除非也指定了 -n 标志

    -n :取消分割多字节字符。仅和 -b 标志一起使用。如果字符的最后一个字节落在由 -b 标志的 List 参数指示的<br />范围之内,该字符将被写出;否则,该字符将被排除

    -d CHAR:以指定的字符为分隔符;

    -f FIELDS:挑选出的字段;

      #:指定的单个字段;

      #-#:连续的多个字段;

      #,#:离散的多个字段;

      #-:指定单个字段到最后

  示例:

    [root@test7_1 sh]# cat issue | cut -b 2-6

    [root@test7_1 sh]# cat /etc/passwd | cut -d: -f2


sort:排序

  格式:

    sort  [OPTION]...  [FILE]...

  选项:

    -n:基于数值大小而非字符进行排序;

    -t CHAR:指定分隔符;

    -k #:用于排序比较的字段;

    -r:逆序排序;

    -f:忽略字符大小写

    -u:重复的行只保留一份;

      重复行:连续且相同;

  示例:

    [root@centos7 sh]# sort -t : -k 3 -n  /etc/passwd

    [root@centos7 sh]# sort -t : -k 3 -n -r /etc/passwd


uniq:报告或移除重复的行

  格式:

    uniq [OPTION]... [INPUT [OUTPUT]]

  选项:

    -c:显示每行的重复次数;

    -u:仅显示未曾重复过的行;

    -d:仅显示重复过的的行;


diff:compare files line by line(文件逐行对比)

  格式:

    diff [OPTION]... FILES

    diff  /PATH/TO/OLDFILE  /PATH/TO/NEWFILE > /PATH/TO/PATCH_FILE

  选项:

    -u:使用unfied机制,即显示要修改的行的上下文,默认为3行;

  示例:

    [root@centos7 sh]# diff issue.bak issue >> buding_issue.patch


patch:向文件打补丁

  格式:

    patch [OPTIONS] -i /PATH/TO/PATCH_FILE /PATH/TO/OLDFILE

    [root@centos7 sh]# patch -i buding_issue.patch issue


    patch /PATH/TO/OLDFILE < /PATH/TO/PATCH_FILE

    [root@centos7 sh]# patch ./issue < ./buding_issue.patch


注:diff和patch结合使用,首先对比两个文件中的差异,生成一个补丁文件。在用补丁文件进行指定文件打补丁


本文出自 “变相怪杰” 博客,谢绝转载!

Linux文本处理"三剑客"--grep