Shell 使用正则表达式

Shell 使用正则表达式,正则表达式是基于模式匹配的文本处理技术的关键所在。想要有效地运用正则表达式,就必须对其有一个基本的理解。

会用ls的用户应该都熟悉通配符模式。通配符可以运用在很多场景中,但是对于文本处理而言,功能还远远不够。正则表达式允许你更精细地描述模式。[a-z0-9_]+@[a-z0-9]+\.[a-z]+.就是一个典型的能够匹配电子邮件地址的正则表达式。看起来有点怪异是吧?别担心,跟着本章学习,你就会发现它其实很简单。

Shell使用正则表达式

实战演练

正则表达式是由字面文本和具有特殊意义的符号组成的。我们可以根据需要,构造出适合的正则表达式来匹配任何文本。正则表达式是很多工具所支持的基本功能。本节将为你讲解正则表达式,但不会介绍其所涉及的Linux/Unix工具。这些工具留待随后的其他攻略中再叙。

下面先来学习正则表达式的规则。

  1. 位置标记

位置标记锚点(position marker anchor)是标识字符串位置的正则表达式。默认情况下,正则表达式所匹配的字符可以出现在字符串中任何位置,见下表。

正则表达式 描述 示例
^ 指定了匹配正则表达式的文本必须起始于字符串的首部 ^tux能够匹配以tux起始的行
$ 指定了匹配正则表达式的文本必须结束于目标字符串的尾部 tux$能够匹配以tux结尾的行
  1. 标识符

标识符是正则表达式的基础组成部分。它定义了那些为了匹配正则表达式,必须存在(或不存在)的字符,见下表。

正则表达式 描述 示例
A字符 正则表达式必须匹配该字符 A能够匹配字符A
. 匹配任意一个字符 Hack.能够匹配HacklHacki,但是不能匹配Hackl2Hackil,它只能匹配单个字符
[] 匹配中括号内的任意一个字符。中括号内可以是一个字符组或字符范围 coo[kl]能够匹配cookcool[0-9]匹配任意单个数字
[^] 匹配不在中括号内的任意一个字符。中括号内可以是一个字符组或字符范围 9[^01]能够匹配9293,但是不匹配9190A[^0-9]匹配A以及随后除数字外的任意单个字符
  1. 数量修饰符

一个标识符可以出现一次、多次或是不出现。数量修饰符定义了模式可以出现的次数,见下表。

正则表达式 描述 示例
? 匹配之前的项1次或0次 colou?r能够匹配colorcolour,但是不能匹配colouur
+ 匹配之前的项1次或多次 Rollno-9+能够匹配Rollno-99Rollno-9,但是不能匹配Rollno-
\* 匹配之前的项0次或多次 co*l能够匹配clcolcoool
{n} 匹配之前的项n [0-9]{3}能够匹配任意的三位数,[0-9]{3}可以扩展为[0-9][0-9][0-9]
{n,} 之前的项至少需要匹配n [0-9]{2,}能够匹配任意一个两位或更多位的数字
{n,m} 之前的项所必须匹配的最小次数和最大次数 [0-9]{2,5}能够匹配两位数到五位数之间的任意一个数字
  1. 其他

还有其他一些特殊字符可以调整正则表达式的匹配方式,见下表。

正则表达式 描述 示例
() 将括号中的内容视为一个整体 ma(tri)?x 能够匹配maxmatrix
\| 指定了一种选择结构,可以匹配 \| 两边的任意一项 Oct (1st \| 2nd)能够匹配Oct 1stOct 2nd
\ 转义字符可以转义之前介绍的特殊字符 a\.b能够匹配a.b,但不能匹配ajb。因为\忽略了.的特殊意义

正则表达式的更多细节请参考:http://www.linuxforu.com/2011/04/sed-explained-part-1/

  1. 补充内容

来看几个正则表达式的例子。能够匹配任意单词的正则表达式:

( +[a-zA-Z]+ +)

开头的+表示需要匹配一个或多个空格。字符组[a-zA-Z]用于匹配所有的大小写字母。随后的+表示至少要匹配一个字母,多者不限。最后的+表示需要匹配一个或多个空格来终结单词。

这个正则表达式无法匹配句子末尾的单词。要想匹配句尾或是逗号前的单词,需要将正则表达式改写为:

( +[a-zA-Z]+[?,.]? +)

[?,.]?表示仅需要匹配问号、逗号或点号中的一个。匹配IP地址很容易。我们知道IP地址是由点号分隔的4组三位数字。[0-9]表示匹配数字。{1,3}表示至少一位数字,至多三位数字:

[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}

或者也可以使用[[:digit:]]表示数字:

[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}\.[[:digit:]]{1,3}

我们知道IP地址是由点号分隔的4个整数(每一个整数的取值范围从0到255),例如192.168.0.2。

这个正则表达式可以匹配文本中的IP地址,但是它并不检查地址的合法性。例如,形如123.300.1.1的IP地址可以被正则表达式匹配,但这却是一个非法的IP地址。

工作原理

正则表达式由复杂的状态机解析,尝试在目标文本中找出最佳匹配。文本可以是管道的输出、文件,甚至是在命令行中输入的字符串。正则表达式的实现方法不止一种,其实现引擎通常会选择最长的匹配。

例如,对于字符串this is a test和正则表达式s.*s,匹配的内容是s is a tes,而非s is。正则表达式的更多细节请参考:http://www.linuxforu.com/2011/04/sed-explained-part-1/

补充内容

前面的多个表格描述了正则表达式中特殊字符的含义。

  1. 处理特殊字符

正则表达式用$^.*+{以及}等作为特殊字符。但是如果我们希望将这些字符作为普通字符使用,应该怎么做呢?来看一个正则表达式:a.txt

该正则表达式能够匹配字符a,然后是任意字符(由.负责匹配),接着是字符串txt。但是我们希望.能够匹配字面意义上的.,而非任意字符。因此需要在.之前加上一个反斜线\(这叫作“字符转义”)。这表明正则表达式希望匹配的是字面含义,而不是它所代表的特殊含义。因此,最终的正则表达式就变成了a\.txt

  1. 可视化正则表达式

正则表达式不容易理解。幸好有一些将正则表达式进行可视化的工具。你可以在页面http://www.regexper.com中输入正则表达式,然后创建出一副图示来帮助你理解。下图就是一个简单的正则表达式的可视化截图。

Shell使用正则表达式

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程

Shell 实例