我们经常会有处理一些文本的需求,Linux下著名的文本处理三剑客:grep、sed、awk,这一篇讲最简单的grep,sed和awk我们后面会讲到。那么在讲解grep之前,我们先说一下正则表达式,这是在使用grep,sed等命令时大部分情况会用到的基础内容。

一、正则表达式概念

二、正则表达式详解

三、扩展正则表达式详解

四、grep命令详解

五、grep结合正则实例




一、正则表达式概念(regex、regexp)

正则表达式,又称正规表示法、常规表示法(英语:Regular Expression,在代码中常简写为regex、regexp或RE),计算机科学的一个概念。正则表达式使用单个字符串来描述、匹配一系列符合某个句法规则的字符串。在很多文本编辑器里,正则表达式通常被用来检索、替换那些符合某个模式的文本。

正则表达式通常用于两种任务:1.验证,2.搜索/替换。用于验证时,通常需要在前后分别加上^和$,以匹配整个待验证字符串;搜索/替换时是否加上此限定则根据搜索的要求而定,此外,也有可能要在前后加上\b而不是^和$。

以上内容来源于百度百科http://deerchao.net/tutorials/regex/common.htm



二、基本正则表达式详解

正则表达式 由一些普通字符和一些元字符(metacharacters)组成。普通字符包括大小写的字母和数字,而元字符则具有特殊的含义,我们下面列出一些常见的元字符:

1. 匹配字符

  • .: 匹配任意单个字符

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

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

  • 字符集合:[:digit:], [:lower:], [:upper:], [:punct:], [:space:], [:alpha:], [:alnum:]

ps:这些字符集合含义在我上篇博客Bash特性总结中第6章Glob通配符有


2. 匹配次数(贪婪模式)

  • *: 匹配其前面的字符任意次

  • .*: 任意长度的任意字符

  • \?: 匹配其前面的字符1次或0次

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


3. 位置锚定

  • ^: 锚定行首,此字符后面的任意内容必须出现在行首

  • $: 锚定行尾,此字符前面的任意内容必须出现在行尾

  • ^$: 空白行

  • \<或\b: 锚定词首,其后面的任意字符必须作为单词首部出现

  • \>或\b: 锚定词尾,其前面的任意字符必须作为单词的尾部出现


4. 分组

  • \(\):如\(ab\)*     # 此处的*修饰的前面括号里的内容,也即ab

  • 后向引用

     \1: 引用第一个左括号以及与之对应的右括号所包括的所有内容

    \2: 引用第一个左括号以及与之对应的右括号所包括的所有内容



三、扩展正则表达式详解

扩展正则表达式大部分与基本正则表达式相同,在此基础上新增了一些次数匹配相关的元字符:

  • ?:匹配其前字符0次或1次

  • +:匹配其前面的字符至少1次

  • {m,n}:匹配其前字符至少m此,至多n次,不用加\转义

  • ():如(ab),将ab作为一个分组

  • |:或者,也即要么是|左边的部分,要么是|右边的部分



四、grep命令详解

grep, egrep, fgrep - print lines matching a pattern        # 打印匹配指定模式的行

SYNOPSIS
       grep [options] PATTERN [FILE...]
       grep [options] [-e PATTERN | -f FILE] [FILE...]
       
    -i:忽略大小写
	-n:在显示符合范本样式的那一列之前,标示出该列的编号
	-v:被模式匹配到的反而不显示,即反向查找
	-o:只显示被模式匹配到的内容
	--color:搜索内容高亮显示
	-i:忽略字符大小写
	-E:使用扩展正则表达式,相当于egrep命令
	-A #:除了被匹配到的,同时显示被模式匹配到的后n行
	-B #:除了被匹配到的,同时显示被模式匹配到的前n行
	-C #:除了被匹配到的,同时显示被模式匹配到的前后n行		

1.按模式匹配到字符串后显示行号

[root@soysauce ~]# grep -n "b..h$" /etc/passwd    # 取出以b开头且中间任意两个字符h结尾的行,并显示行号
1:root:x:0:0:root:/root:/bin/bash
33:mysql:x:101:158::/home/mysql:/bin/bash
34:apache:x:102:159::/home/apache:/bin/bash
36:hadoop:x:501:501::/home/hadoop:/bin/bash

2.只显示没有被模式匹配到的行

[root@soysauce ~]# grep  -v "nologin$" /etc/passwd    # -v反向查找,匹配到的字符串反而不显示
root:x:0:0:root:/root:/bin/bash
sync:x:5:0:sync:/sbin:/bin/sync
shutdown:x:6:0:shutdown:/sbin:/sbin/shutdown
halt:x:7:0:halt:/sbin:/sbin/halt
news:x:9:13:news:/etc/news:
mysql:x:101:158::/home/mysql:/bin/bash
apache:x:102:159::/home/apache:/bin/bash
hadoop:x:501:501::/home/hadoop:/bin/bash

3.只显示被匹配到的字符串,并不显示整行

[root@soysauce ~]# grep -o  "root" /etc/passwd        # -o只显示匹配到的字符串
root
root
root
root

4.匹配到的字符串给予高亮显示

[root@soysauce ~]#  grep --color "r..t" /etc/passwd
root:x:0:0:root:/root:/bin/bash       # 额,这里高亮效果没显示出来,你在终端上敲此命令就可以看到效果了
operator:x:11:0:operator:/root:/sbin/nologin    
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

5.使用扩展的正则表达式

[root@soysauce ~]# grep -E --color "root|ftp" /etc/passwd    # 查找包含root或ftp的行
root:x:0:0:root:/root:/bin/bash
operator:x:11:0:operator:/root:/sbin/nologin
ftp:x:14:50:FTP User:/var/ftp:/sbin/nologin

6.按模式匹配到行之后,其后面n行也一起显示

[root@soysauce ~]# grep -A 2 "root" /etc/passwd
root:x:0:0:root:/root:/bin/bash
bin:x:1:1:bin:/bin:/sbin/nologin                # 这是第一次匹配到root时所在行的后两行
daemon:x:2:2:daemon:/sbin:/sbin/nologin
--
operator:x:11:0:operator:/root:/sbin/nologin
games:x:12:100:games:/usr/games:/sbin/nologin   # 这是第二次匹配到root时所在行的后两行
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin

7.按模式匹配到行之后,其前面n行也一起显示

[root@soysauce ~]# grep -B 2 "root" /etc/passwd    
root:x:0:0:root:/root:/bin/bash             # 因为第一次匹配到的root是第一行,所以就没有前2行
--
news:x:9:13:news:/etc/news:    
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin    # 这是第二次匹配到root时所在行的前两行
operator:x:11:0:operator:/root:/sbin/nologin

8.按模式匹配到行之后,其前后n行也一起显示

[root@soysauce ~]# grep -C 2 "root" /etc/passwd
root:x:0:0:root:/root:/bin/bash    
bin:x:1:1:bin:/bin:/sbin/nologin    # 因为第一次匹配到的root是第一行,所以就没有前2行,只有后两行
daemon:x:2:2:daemon:/sbin:/sbin/nologin
--
news:x:9:13:news:/etc/news:
uucp:x:10:14:uucp:/var/spool/uucp:/sbin/nologin
operator:x:11:0:operator:/root:/sbin/nologin    # 此行是被模式匹配到的行
games:x:12:100:games:/usr/games:/sbin/nologin
gopher:x:13:30:gopher:/var/gopher:/sbin/nologin


五、grep结合正则实例

1、显示/proc/meminfo文件中以不区分大小的s开头的行

[root@soysauce ~]# grep "^[sS]" /proc/meminfo 
SwapCached:          0 kB
SwapTotal:           0 kB
SwapFree:            0 kB
Slab:            82072 kB
[root@soysauce ~]# grep -i "^s" /proc/meminfo    # 与第一条命令相同
[root@soysauce ~]# egrep "^(s|S)" /proc/meminfo  # 与第一条命令相同

2、取出默认shell为/bin/bash的用户列表

[root@soysauce ~]# grep "bash$" /etc/passwd | cut -d: -f1
root
mysql
apache
hadoop

3、取出默认shell为bash,且其用户ID号最小的用户的用户名

[root@soysauce ~]# grep "bash" /etc/passwd | sort -n -t: -k3 | cut -d: -f1 | head -1
root

4、显示/etc/inittab中以#开头,且后面跟一个或多个空白字符,而后又跟了任意非空白字符的行

[root@soysauce ~]# egrep "^#[[:space:]]+[^[:space:]]" /etc/inittab     # 内容过长,只截取少部分
# inittab       This file describes how the INIT process should set up
#               the system in a certain run-level.
# Author:       Miquel van Smoorenburg, <miquels@drinkel.nl.mugnet.org>
#               Modified for RHS Linux by Marc Ewing and Donnie Barnes
# Default runlevel. The runlevels used by RHS are:
#   0 - halt (Do NOT set initdefault to this)

5、显示/etc/inittab中包含了:一个数字:(即两个冒号中间一个数字)的行

[root@soysauce ~]# egrep ":[[:digit:]]:" /etc/inittab 
id:3:initdefault:
l0:0:wait:/etc/rc.d/rc 0
l1:1:wait:/etc/rc.d/rc 1
l2:2:wait:/etc/rc.d/rc 2
l3:3:wait:/etc/rc.d/rc 3
l4:4:wait:/etc/rc.d/rc 4
l5:5:wait:/etc/rc.d/rc 5
l6:6:wait:/etc/rc.d/rc 6
x:5:respawn:/etc/X11/prefdm -nodaemon

6、显示/boot/grub/grub.conf文件中以一个或多个空白字符开头的行

[root@soysauce ~]# egrep "^[[:space:]]+" /boot/grub/grub.conf 
	root (hd0,0)
	kernel /boot/vmlinuz-2.6.18-308.el5 ro root=LABEL=/ clock=tsccount ide0=noprobe
	initrd /boot/initrd-2.6.18-308.el5.img

7、显示/etc/inittab文件中以一个数字开头并以一个与开头数字相同的数字结尾的行

[root@soysauce ~]# egrep "^([[:digit:]]).*\1$" /etc/inittab 
1:2345:respawn:/sbin/mingetty tty1
2:2345:respawn:/sbin/mingetty tty2
3:2345:respawn:/sbin/mingetty tty3
4:2345:respawn:/sbin/mingetty tty4
5:2345:respawn:/sbin/mingetty tty5
6:2345:respawn:/sbin/mingetty tty6

8.ifconfig命令中四位点分十进制数截取

[root@soysauce ~]# ifconfig|egrep --color  -o '(\b([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\b.){3}\b([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\b'
x.x.x.x
x.x.x.x
x.x.x.x
x.x.x.x
x.x.x.x
x.x.x.x
127.0.0.1
255.0.0.0

8.ifconfig命令中ip地址截取

[root@soysauce ~]# ifconfig |egrep -o --color '\<([1-9]|[1-9][0-9]|1[0-9]{2}|2[01][0-9]|22[0-3])\>(\.\<([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4])\>){2}\.\<([1-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-4])\>'
x.x.x.x
x.x.x.x
127.0.0.1





附:常用正则表达式