正则表达式(Regular Expression):一个正则表达式通常被称为一个模式(pattern),为用来描述或者匹配一系列符合某个句法规则的字符串。正则表达式这个概念最初是由Unix中的工具软件(例如sed和grep)普及开的。 

 

下面以grep(Galobal research Regular Expression and Printing)为例简要介绍一下正则表达式的元字符(metacharacter):

grep是一个文本过滤工具。

在具体介绍正则表达式的元字符之前需要先了解一下grep的格式、常用选项:

grep的格式

 grep [options] PATTERN  file1 ...

grep的常用选项

 -v :对结果取反
 -i :忽略字母大小写
 -o :仅显示匹配到的字符串
 -E :支持扩展正则表达式
 -A n :显示匹配到内容的后n行
 -B n :显示匹配到内容的前n行
 -C n :显示匹配到内容的前后各n行
 -n, --line-number :显示出匹配到的行的行号

为了方便一下举例说明,准备了一个文本文件,内容如下:

 
  1. # vim test  
  2.     line 1: hello,xixi  
  3.     line 2: Hello,haha  
  4.     line 3: hello,heihei  
  5.     line 4: Hi,everybody 

. 匹配任意单个字符

 
  1. # grep "hi." test  
  2.         Line 4: hi,everybody 

[] 匹配范围内的任意单个字符

 
  1. # grep "[13]" test  
  2.         Line 1: hello,xixi  
  3.         Line 3: hello,heihei 

[^] 匹配范围之外的任意单个字符(这个和[]类似,不再举例说明)

    

编辑上面的test文件,将内容改成如下:

 
  1. # vim test  
  2.     line1:hello,xixi  
  3.     LINE2:HELLO,HAHA  
  4.     line 3: hello,heihei  
  5.     LINE 4: HI,EVERYBODY      
  6.     how are you? 

[:upper:] 匹配任意大写字母

 
  1. # grep "[[:upper:]]" test  
  2.     LINE2: HELLO,HAHA  
  3.     LINE 4: HI,EVERYBODY 

[:lower:] 匹配任意小写字母

 
  1. # grep "[[:lower:]]" test  
  2.     line1:hello,xixi  
  3.     line 3: hello,heihei  
  4.     how are you

[:alpha:] 匹配任意大小写字母

 
  1. # grep "[[:alpha:]]" test
  2. line1:hello,xixi
  3. LINE2:HELLO,HAHA
  4. line 3: hello,heihei
  5. LINE 4: HI,EVERYBODY
  6. how are you?

[:digit:] 匹配任意单个数字

 
  1. # grep "[[:digit:]]" test  
  2.     line1:hello,xixi  
  3.     LINE2:HELLO,HAHA  
  4.     line 3: hello,heihei      
  5.     LINE 4: HI,EVERYBODY 

[:alnum:] 匹配任意大小写字母和数字

 
  1. # grep "[[:alnum:]]" test    
  2. line1:hello,xixi  
  3. LINE2:HELLO,HAHA  
  4. line 3: hello,heihei  
  5. LINE 4: HI,EVERYBODY  
  6. how are you

[:space:]   匹配空格和tab键

 
  1. # grep "[[:space:]]" test  
  2.     line 3: hello,heihei  
  3.     LINE 4: HI,EVERYBODY  
  4.     how are you? 

[:punct:]  匹配标点符号

 
  1. # grep "[[:punct:]]" test    
  2. line1:hello,xixi  
  3. LINE2:HELLO,HAHA  
  4. line 3: hello,heihei  
  5. LINE 4: HI,EVERYBODY  
  6. how are you? 

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

 
  1. # grep "red*" /etc/passwd  
  2. redhat:x:501:501::/home/redhat:/bin/bash 
   

.*  任意长度的任意字符,属于贪婪模式

 
  1. # grep -o  "red.*" /etc/passwd   
  2.     redhat:x:501:501::/home/redhat:/bin/bash 

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

为了方便举例,在test文件中新加如下几行:

 rot
 roto
 rtoooo
 root

 
  1. # grep "roo\?" test  
  2.     rot  
  3.     roto  
  4.     roo

\{m,n\} 匹配此前字符最少m次,最多n次

 
  1. # grep "ro\{2,3\}" test   
  2. roo

 \{m,\} 匹配此前字符最少m次

 
  1. # grep "ro\{1,\}" test
  2. rot
  3. roto
  4. root

 \{0,n\} 匹配此前字符0次到n次

 
  1. # grep "ro\{0,3\}" test   
  2. how are you?  
  3. rot  
  4. roto  
  5. rtoooo  
  6. roo

 \{m\} 匹配此前字符m次,属于精确匹配

 
  1. # grep  -o "ro\{1\}" test    //-o只显示被匹配到的字符串
  2. ro  
  3. ro  
  4. ro 

 
 引用:
  \(\) 用于引用括号中的内容,从左至右第一个左括号开始匹配,后面引用时用\1,\2,...

 
  1. # grep "\(xi\)\1" test   
  2. line1:hello,xixi 

 

  锚定符:

 ^ 行首锚定

 
  1. # grep --color=auto "^root" /etc/passwd  
  2. root:x:0:0:root:/root:/bin/bash 

 $ 行尾锚定

 
  1. # grep "\?$" test   
  2. how are you? 

 ^$ 空白行

 
  1. # grep "^$" /etc/inittab 

 \< 锚定词首(\b)

 
  1. # grep "\<r" test   
  2. rot  
  3. roto  
  4. rtoooo  
  5. root 

 \> 锚定词尾(b\)

 
  1. # grep "\<r.*t\>" test   
  2. rot  
  3. root 

下面综合上面所介绍的元字符举几个例子:

在写正则表达式时,需要事先分析所要查找的字符串的特征,然后再看使用哪些元字符,可以更快捷、更简单。

查找当前系统上名字为user1的用户的帐号的相关信息

 
  1. # grep "^user1\>" /etc/passwd  
  2. user1:x:503:503::/home/user1:/bin/bash 

查找当前系统上名字为user后面跟了数字的用户的相关信息;

 
  1. # grep "^user[[:digit:]]\{1,\}" /etc/passwd  
  2. user1:x:503:503::/home/user1:/bin/bash  
  3. user11:x:505:505::/home/user11:/bin/bash 

查找当前系统上以其为附加组的用户有两个或两个以上的组的相关信息

 
  1. # grep "," /etc/group  
  2. bin:x:1:root,bin,daemon  
  3. daemon:x:2:root,bin,daemon  
  4. sys:x:3:root,bin,adm  
  5. adm:x:4:root,adm,daemon  
  6. lp:x:7:daemon,lp 

查找当前系统上其用户帐号密码最长使用期为99999天的用户帐号的相关信息;

 
  1. # cat /etc/shadow | cut -d: -f5 | grep "99999" 

分析/etc/inittab文件中如下两行的文本特征,请写出可以精确找到类似两行的模式,而且要求每一行中出现在数字必须相同:

l1:1:wait:/etc/rc.d/rc 1
l3:3:wait:/etc/rc.d/rc 3

 
  1. # grep "l\([13]\).*\1" /etc/inittab  
  2. l1:1:wait:/etc/rc.d/rc 1  
  3. l3:3:wait:/etc/rc.d/rc 3 

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

 
  1. # grep "^[sS]" /proc/meminfo  
  2. SwapCached:          0 kB  
  3. SwapTotal:     1052248 kB  
  4. SwapFree:      1052248 kB  
  5. Slab:            27468 kB 

显示/etc/passwd中以nologin结尾的行;

 
  1. # grep "\<nologin$" /etc/passwd 

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

 
  1. # grep "^#[[:space:]]\{1,\}[^[:space:]].*" /etc/inittab  

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

 
  1. # grep ":[0-9]:" /etc/inittab 

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

 
  1. # grep "^[[:space:]]\{1,\}" /boot/grub/grub.conf  

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

 
  1. # grep "^\([0-9]\).*\1$" /etc/inittab