linux学习笔记: grep命令,正则表达式

linux学习笔记:grep命令,正则表达式

linux运维笔记


  • 简介 
    grep命令是一个最初用于Unix操作系统的命令行工具,在给出文件列表或者标准输入之后,grep会对匹配一个或者多个正则表达式的文本进行搜索,并且只输出匹配或者不匹配的行或者文本。(参见维基百科) 
     
    正则表达式是计算机科学的一个概念,正则表达式使用单个字符串来描述、匹配一系列匹配某个句法规则的字符串。在很多文本编辑器里面,正则表达式通常被用来检索、替换那些匹配某个模式的文本。(参见维基百科)


  • grep, 正则表达式的作用 
    在生产环境或者实验环境中,我们经常会对linux操作系统下的日志以及配置文件进行文本处理,从中截获、修改我们感兴趣的内容,进行分析和处理。通过grep命令,结合正则表达式,可以灵活地完成各种文本处理,从而达到事半功倍的目的。 
  • grep命令的常用选项 
    完全详细的grep命令的选项以及作用,可以参照man手册,或者google,这里仅总结一些常用的选项:
命令选项 解释
-v 显示不被pattern匹配到的行
-i 忽略字母的大小写
-n 显示匹配的行号
-c 统计匹配的行数
-o 仅显示匹配到的字符串
-q 静默模式,不输出任何信息
-A <num> 不仅输出匹配的行,同时输出该匹配行后面的num行
-B <num> 不仅输出匹配的行,同时输出该匹配行之前的num行
-C <num> 不仅输出匹配的行,同时输出该行前后各num行
-e 实现多个选项之间的逻辑or关系
-w 匹配整个单词
-E 使用egrep扩展模式进行正则匹配
-F 相当于fgrep(fast grep),并不支持正则表达式

$ cat /etc/nsswitch.conf | grep -v "^#" | grep -v "^$" #删空行和注释行
passwd:     files sss
shadow:     files sss
group:      files sss
......
......
$ echo "HELLO" | grep -i "hello" #不区分大小写的匹配
HELLO
$ cat /etc/passwd | grep -c bash #统计使用bash用户的数量
3
......
......
$ cat /etc/passwd | grep -n bash #匹配使用bash用户的行并添加行号
1:root:x:0:0:root:/root:/bin/bash
23:user1:x:1000:1000::/home/user1:/bin/bash
24:guest:x:1002:1002::/home/guest:/bin/bash
......
......

$ cat /etc/passwd | grep -o bash #仅仅显示匹配到的字符串本身
bash
bash
bash
......
......
$ cat /etc/passwd | grep -q bash; echo $? #静默模式
0
$ cat /etc/passwd | grep -q abcdefg; echo $? #静默模式   
1
......
......
$ cat grep -A3 -B3 "^\bshutdown\b" /etc/passwd #shutdown前后3行
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
$ cat grep -C3 "^\bshutdown\b" /etc/passwd #同上
adm:x:3:4:adm:/var/adm:/sbin/nologin
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
mail:x:8:12:mail:/var/spool/mail:/sbin/nologin
......
......
$ grep -e "root"  -e "lp"  -e "ftp" /etc/passwd #逻辑或
root:x:0:0:root:/root:/bin/bash
lp:x:4:7:lp:/var/spool/lpd:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin
......
......
$ cat 1.txt 
/bin/bash
bash/bin
bash
/bin/bash/bin
binbashbin
$ cat 1.txt | grep -w bash #-w选项无法匹配binbashbin中的bash
/bin/bash
bash/bin
bash
/bin/bash/bin
......
......

  • linux,grep,与正则表达式 
    正则表达式的实现(参见:正则引擎)有很多种,在linux操作系统里面,默认引擎为PCRE(Perl Compatible Regular Expressions),依照维基百科,PCRE库、Perl语言、PHP语言、Python语言,对正则表达式的支持是最好的。linux系统的程序,如grep, sed, awk, vim, less, nginx, varnish等,都支持正则表达式。 
     
    针对grep程序,支持基本的正则表达式(BRE)以及扩展的正则表达式(ERE),可以通过grep -E命令或者egrep命令,使用扩展的正则表达式。 
     
    更多的正则表达式的内容,可以参见linux下面的man手册: man 7 regex 

  • 正则表达式的元字符 
    在正则表达式中,具有特殊意义的字符集,称为元字符。常用的元字符如下表所示:

元字符 含义
^ 行首锚定
$ 行尾锚定
. 匹配任意单个字符
[] []内任意单一字符
[^] 除[]内任意单一字符
* *前面的字符重复0次或者多次
\+ \+前面字符重复1次或者多次
\? ?前面的字符重复0次或者1次
\ 转义符
\{n\} 前面字符重复n次
\{n,\} 前面字符重复n次(包括n次)以上
\{m,n\} 前面的字符重复m次(包括m次)和n次(包括n次)之间
[:alnum:] 字母和数字
[:alpha:] 代表任何英文大小写字母
[:lower:] 小写字母
[:upper:] 大写字母
[:blank:] 水平空白符
[:space:] 垂直空白字符
[:cntrl:] 不可打印的控制字符(退格、删除、警铃……)
[:digit:] 十进制数字
[:graph:] 可打印的空白字符
[:pnuct:] 标点符号
[:xdigit:] 十六进制数字

示例如下所示:

1. 显示/proc/meminfo文件中以大s或者小s开头的行:
$ cat /proc/meminfo | grep -i "^s.*$"
$ cat /proc/meminfo | grep "^[sS].*$"

2.显示CentOS7上面所有系统用户的用户名和UID:
$ cat /proc/meminfo | grep -v "root" | grep -v "\b[0-9]\{4,\}\b"

3.取出/etc/rc.d/init.d/functions的基名
 echo "/etc/rc.d/init.d/functions" | egrep -o "/[[:alpha:]]+$" |  \
 egrep -o "[[:alpha:]]+"

4.使用egrep取出上面路径的目录名 #贪婪匹配
echo "/etc/rc.d/init.d/functions" | egrep -o "/.*/"

5.找出/etc/rc.d/init.d/functions文件中行首为某单词(包括下划线)后面跟一个小括号的行
$ cat /etc/rc.d/init.d/functions  | egrep "^[_[:alpha:]]+\(\)"
  • 正则表达式的分组 
    将一个或者多个字符捆绑在一起,当做一个整体进行处理,例如:\(root\)\+ 
    分组括号中的匹配模式匹配到的内容会被正则引擎记录于内部变量当中,这些变量的分组的命名方式为\1, \2, \3,…… 
    当然,我们也可以自己定义分组名称。利用(?<Word>\w+),这样就会将\w+匹配到的内容赋值给分组Word。可以通过\k<Word>引用这个分组1。 
    分组的语法格式如下表所示:
表达式 解释
(exp) 匹配exp, 捕获文本到自动命名的组里面: \1, \2, …
(?<name>exp) 匹配exp,捕获文本到名称为name的组里面
(?:exp) 匹配exp,不捕获匹配的文本
(?=exp) 匹配exp前面的位置,但是并不包括exp本身
(?<=exp) 匹配exp后面的位置,但是并不包括exp本身
(?!exp) 匹配后面不是exp的位置,不包括那个不是exp的模式
(?<!exp) 匹配前面不是exp的位置,不包括那个不是exp的模式

其中的(?=exp)被称为零宽先行断言,其中的(?<=exp)被成为零宽后行断言。 

使用案例如下所示:

1. 找出/etc/passwd下面用户名同shell名的行
$ cat /etc/passwd | grep -P "^\b(\w+):\b.*\1$"
......
......
2.匹配开头是/bin/的内容,但是并不包括/bin/本身
[root@centos7-front1 ~]# cat -n 1.txt 
     1  /bin/bash
     2  /bin/bash/bin/
     3  <bash>
     4  <bash
[root@centos7-front1 ~]# cat 1.txt | grep -noP "(?<=/bin).*"
1:/bash
2:/bash/bin/
......
......
3.匹配结尾为/bin/的内容,但是并不包括/bin/本身
[root@centos7-front1 ~]# cat -n 1.txt 
     1  /bin/bash
     2  /bin/bash/bin/
     3  <bash>
     4  <bash
[root@centos7-front1 ~]# cat 1.txt | grep -noP "^.*(?=/bin/$)"
2:/bin/bash
......
......
3.匹配由两个尖括号包裹的内容,但是并不包括两个尖括号本身
[root@centos7-front1 ~]# cat -n 1.txt 
     1  /bin/bash
     2  /bin/bash/bin/
     3  <bash>
     4  <bash
[root@centos7-front1 ~]# cat 1.txt | grep -noP "(?<=<).*(?=>)"
3:bash
......
......
4.匹配简单html标签
$ echo "<font color=#ff0000>color font</font>" \
 | grep -oP "(?<=>).*(?=</font>)"
color font
......
......
5.匹配出/etc/passwd文件中用户id和数组id相同的用户
$ grep -P ".*\b:(?<UID>\w+):\b\k<UID>.*$" /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
nobody:x:99:99:Nobody:/:/sbin/nologin
avahi-autoipd:x:170:170:Avahi IPv4LL Stack:/var/lib/avahi-autoipd:/sbin/nologin
dbus:x:81:81:System message bus:/:/sbin/nologin
abrt:x:173:173::/etc/abrt:/sbin/nologin
tss:x:59:59:Account used by the trousers package to sandbox the tcsd daemon:/dev/null:/sbin/nologin
postfix:x:89:89::/var/spool/postfix:/sbin/nologin
sshd:x:74:74:Privilege-separated SSH:/var/empty/sshd:/sbin/nologin
user1:x:1000:1000::/home/user1:/bin/bash
guest:x:1002:1002::/home/guest:/bin/bash
nscd:x:28:28:NSCD Daemon:/:/sbin/nologin
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
  • 贪婪模式与懒惰模式 
    当正则表达式中包含能接受重复的限定符时,通常的行为是(在使整个表达式能得到匹配的前提下)匹配尽可能多的字符。以这个表达式为例:a.*b,它将会匹配最长的以a开始,以b结束的字符串。如果用它来搜索aabab的话,它会匹配整个字符串aabab。这被称为贪婪匹配 
     
    有时,我们更需要懒惰匹配,也就是匹配尽可能少的字符。前面给出的限定符都可以被转化为懒惰匹配模式,只要在它后面加上一个问号?。这样.*?就意味着匹配任意数量的重复,但是在能使整个匹配成功的前提下使用最少的重复。 
     
    懒惰限定符如下表所示:
限定符 说明
*? 重复任意次,但是尽可能少地重复
+? 重复1次或者更多次,但是尽可能少地重复
?? 重复0次或者1次,但是尽可能少地重复
{n,m}? 重复n到m次,但是尽可能少地重复
{n,}? 重复n次,但是尽可能少地重复

使用示例如下所示:

[root@centos7-front1 ~]# echo "aababab" | grep -oP "a.*b"
aababab
[root@centos7-front1 ~]# echo "aababab" | grep -oP "a.*?b"
aab
ab
ab
[root@centos7-front1 ~]# echo "aababab" | grep -oP "a.+?b"
aab
abab
[root@centos7-front1 ~]# echo "aababab" | grep -oP "a.??b"
aab
ab
ab
[root@centos7-front1 ~]# echo "aababab" | grep -oP "a.{0,1}?b"
aab
ab
ab
[root@centos7-front1 ~]# echo "aababab" | grep -oP "a.{1,}?b" 
aab
abab

注释:


  1. 使用分组的时候,最好使用grep -P命令,使用Perl正则扩展。 

原创文章,作者:jiangche00,如若转载,请注明出处:http://www.178linux.com/72707

(0)
jiangche00jiangche00
上一篇 2017-04-06
下一篇 2017-04-07

相关推荐

  • ​学会用各种姿势备份MySQL数据库

                学会用各种姿势备份MySQL数据库 前言 为什么需要备份数据? 数据的备份类型 MySQL备份数据的方式 备份需要考虑的问题 设计合适的备份策略 实战演练 使用cp进行备份 使用mysqldump+复制BINARY …

    Linux干货 2016-04-27
  • ip命令详解

      Linux中的ip命令功能强大,可以完成接口配置、路由管理等任务。   格式:ip [ OPTIONS ] OBJECT { COMMAND | help }   下面使用ip命令来完成一些常用的操作:     1、查看接口状态       ip link show [设备名…

    Linux干货 2016-01-14
  • 文本处理之sed

     sed:是一种行编辑器,它在处理行时会把要处理的行读入模式空间中,处理的是模式空间的内容,一行一行的处理,然后把处理结果显示在屏幕中,不对原文做修改,除非强制重定向。   好处:可同时编辑一个或多个文件,简化了对文件的反复操作。 sed用法:   格式: sed [options ]…'script&#0…

    Linux干货 2016-08-15
  • 17周博客作业 LVS+nginx+php(nginx与php分离)

    1、结合图形描述LVS的工作原理; LVS是一种用软件实现的LB集群; 作用于传输层; LVS工作原理:通过Director调度把用户请求按照分配算法分配给后端的Real server,然后由后端Real server响应客户请求; lvs模式分为三种。 lvs-nat: 多目标的DNAT:通过将请求报文的目标地址和目标端口修改为挑选出某…

    Linux干货 2016-11-07
  • ansible高级应用

    上一篇博客介绍了ansible的基础应用Modules,博客地址 http://www.178linux.com/14860 。这次介绍下Ansible的另一个核心模块Playbooks。   Ansible的核心模块:     Ansible core:   &nbs…

    Linux干货 2016-04-18
  • 2016 10 19 第5天作业

    20161019第5天作业 软链接和硬链接的区别 硬链接 ①硬链接文件不能跨分区创建 ②一个硬链接文件的删除不影响其他链接的访问 ③链接文件指向的源文件被删除后,链接文件还能正常访问源文件的数据 ④硬链接的文件类型是 –  普通文件 ⑤硬链接和源文件的属性(大小,权限,时间戳,Inode号)相同 ⑥硬链接不能对目录创建 ⑦创建硬链接会增…

    Linux干货 2016-10-20

评论列表(1条)

  • renjin
    renjin 2017-04-12 11:17

    详细的介绍了grep 以及正则表达式,内容写的很不错,版本也非常好,赞!