本文是帮助刚接触正则表达式或用过还没有弄懂的童鞋理解正则表达式,主要描述了正则表达式是个什么东东,而不是讨论用法和工作原理。不过也欢迎高手批评指正,以更好的帮助新手。
无论是Java、Shell、Python、Perl都用正则表达式,说明它肯定是个好东西,那它到底是一个什么样东东呢?
正则表达式曾是我学Shell时最头大的一个问题,当时总以为他是条命令啥的,显然他不是,也显然是个表达式,那什么叫表达式呢,这个概念先不管,应该都听说过算术表达式吧,那算术表达式是啥呢,怎么描述呢,在数学课程中是这样描述的:由数字和运算符号组成的式子,可以简单清晰地记录或描述计算过程和内容【本句摘自百度百科】,我们只看前半句,说明是个式子,式子都知道吧,简单的说是一句话,有特定含义的一句话,当然编程语言中的算术表达式还是个式子,正则表达式也是个式子。
现在知道它也是一种表达式了,那他是干嘛用的呢?算术表达式是用于描述计算过程和内容的,正则表达式是描述了一批而不是一个字符串,为什么要描述一批字符串呢,比如你要显示当成目录下所有的以.c为后辍的文件,怎么办呢,都知道linux下显示文件是用ls命令,如果linux懂人的自然语言,那那样就可以这样:
$ ls 所有以.c为后辍的文件
可惜它不懂,所以会报错,你可能认为他不懂中文,你也可以用英文试试。
那我们怎么把这个的意思传达给它呢,肯定是要商定一个共同语言,正则表达式就是人与程序的一种共同语言,含通配符的表达式也是一种,不过通配符简单点,所以我们先用通配符试试:
elwin@Ubuntu64:~/work$ ls 1.c 1.java 2.c 2.java 3.c file1.txt elwin@Ubuntu64:~/work$ ls *.c 1.c 2.c 3.c其中星号“*”表示任意字符串,于是用这个简单的*.c就是描述了所用以.c结尾的字符串,这是一批字符串,而不是一个,如果另一个字符串属于这一批字符串,就可以说该字符串与该表达式匹配成功,于是上例中所以匹配成功的都显示出来了。(说明一点,上述的通配符表达式不是被ls扩展,而是被shell扩展的,文章最后的附录有个脚本验证,有兴趣可以试试,但不知道这点并不会阻碍你对本文的理解)
虽然那不是正则表达式,但思想是一样的,本质是表达式中的某些的字符有特殊含义,当然这个特殊含义是相对就言的,例如上面的星号“*”对你而言就是星号,但对Shell而言,星号代表任意字符串,而在正则表达式中又不同,因为正则表达式与通配符就语法和符号代表的特殊含义是不同的,正规表达式的表达能力要强大得多,你可以认为正则表达式是通配符升级版,其实正则表达式是一种计算机的一个重要理论,它被应用于编译器的词法分析,跟有穷自动机有重要的联系,关于历史,先不讨论了。与上面的等价的用正则表达式是这样的:
.*\.c暂时看不懂没关系,下面慢慢解释,我们先用sed试一下吧:
elwin@Ubuntu64:~/work$ ls |sed -n '/.*\.c$/p' 1.c 2.c 3.c用斜杠里面包括的(不含斜杠)就是一个正则表达式,(这条组合命令你不知道没关系,你只需要知道他的作用是:显示当前目录下,文件名符合该正则表达式的所有文件)。下面解释一下这个正则表达式,其中的点“.”代表任意字符,星号“*”表示将前面的那个字符重复n次(包括0次),这两个的意思就是将任意字符重复篇,如果正则表达式就这两个,后面不写了,那就表示世上所有字符串,我们再试一下吧:
elwin@Ubuntu64:~/work$ ls |sed -n '/.*/p' 1.c 1.java 2.c 2.java 3.c file1.txt
看吧,所有文件都列出来了,说明都匹配成功了。现在我们继续分析刚刚的表达式,星号后面的反斜杠表示转义,即把接下来的那个字符(这里是点号)当作普通字符,没有特珠含义,如果不在前面加上反斜杠就代表任何字符了,接下来的“c”在正则表达式里属于普通字符串,再接下来的美元符“$”表示换行符,于是整个表达式的意思就是:任意长度的字符串,连上“.c”,再接一个换行符,如果不接这个换行符,那“1.cc”也会被匹配,如:
elwin@Ubuntu64:~/work$ touch 1.cc elwin@Ubuntu64:~/work$ ls |sed -n '/.*\.c/p' 1.c 1.cc 2.c 3.c
你可能有个疑问,哪到到底算特珠符号,哪些算普通符号呢,这当然有个规定了,这此特殊符号都有各自的含义,这种文章网上很多,大家可以搜索,也可以看man手册(man grep就可以),也可以参考此文,本文主要目是帮助初学者理解正则表达式,而不是讨论详细用法。
还有一点需要说明,Shell、Java、Perl都有正规表达式,不过他们之间只有细微的区别,很多都是通用,其中以Perl中的正则表达式最强大,原因是Perl解释器强大。
附录:
1.验证shell会扩展星号的脚本,将以下内容保存到test.sh:
#!/bin/sh echo "$*"这里的“$*”代表所以输入参数。加上执行权限运行./test.sh *.c,结果如下:
elwin@Ubuntu64:~/work$ ls 1.c 1.cc 1.java 2.c 2.java 3.c file1.txt test.sh elwin@Ubuntu64:~/work$ ./test.sh *.c 1.c 2.c 3.c
说明:本文章纯属个人观点,不保证绝对正确,欢迎大家批评和指正,同时我自己也会对本文不断的更新和完善。