正值表达式使用指南

1         概述

正值表达式(regular expression)是一个描述字符模式的对象,它是一种可以用于模式匹配替换的强有力的工具,主要应用于处理文本操作,应用非常广泛,很多开发语言都对正值表达式进行支持,比如:javac#javascriptperl等。

本文档是关于正值表达式使用指南。包括:基本概念、开发规范、java处理方式、javascript处理方式、代码实例等。

通过该文档可以了解正值表达式的基本知识、开发规范、常用的开发方式等,并能够通过javajavascript语言进行基于正值表达式的开发工作。

本文档适合所有Java开发人员。

2         基础知识

2.1         基本概念

正则表达式最早是由数学家Stephen Kleene1956年提出,主要使用在字符字符串的格式比对,后来在信息领域广为应用,现在已经成为ISO(国际标准组织)的标准之一。

一个正则表达式,就是用某种模式去匹配一类字符串的一个公式。可以把数小时辛苦而且易错的文本处理工作压缩在几分钟(甚至几秒钟)内完成。正则表达式被各种文本编辑软件、类库(例如Rogue Wavetools.h++)、脚本工具(像awk/grep/sed)广泛的支持,而且像MicrosoftVisual C++这种交互式IDE也开始支持它了。

2.2         直接量字符

构造

匹配

 

 

字符

x

字符 x

//

反斜线字符

/0n

带有八进制值 0 的字符 n (0 <= n <= 7)

/0nn

带有八进制值 0 的字符 nn (0 <= n <= 7)

/0mnn

带有八进制值 0 的字符 mnn0 <= m <= 30 <= n <= 7

/xhh

带有十六进制值 0x 的字符 hh

/uhhhh

带有十六进制值 0x 的字符 hhhh

/t

制表符 ('/u0009')

/n

新行(换行)符 ('/u 000A ')

/r

回车符 ('/u000D')

/f

换页符 ('/u 000C ')

/a

报警 (bell) ('/u0007')

/e

转义符 ('/u001B')

/cx

对应于 x 的控制符

 

在正值表达式中,许多标点符号具有特殊的含义。它们是:^ $ . * + ? = ! : | / / () [] {}

斜线字符 ('/') 用于引用转义构造,如上表所定义的,同时还用于引用其他将被解释为非转义构造的字符。因此,表达式 // 与单个反斜线匹配,而 /{ 与左括号匹配。

2.3         字符类

将单独的字符放入方括号内可以组合为字符类(character class)。

符类可以出现在其他字符类中,并且可以包含并集运算符(隐式)和交集运算符 (&&)。并集运算符表示至少包含其某个操作数类中所有字符的类。交集运算符表示包含同时位于其两个操作数类中所有字符的类。

字符类运算符的优先级如下所示,按从最高到最低的顺序排列:

1    

字面值转义    

/x

2    

分组

[...]

3    

范围

a-z

4    

并集

[a-e][i-u]

5    

交集

[a-z&&[aeiou]]

注意,元字符的不同集合实际上位于字符类的内部,而非字符类的外部。例如,正则表达式 . 在字符类内部就失去了其特殊意义,而表达式 - 变成了形成元字符的范围。

字符类

[abc]

ab c(简单类)

[^abc]

任何字符,除了 ab c(否定)

[a-zA-Z]

a z A Z,两头的字母包括在内(范围)

[a-d[m-p]]

a d m p[a-dm-p](并集)

[a-z&&[def]]

de f(交集)

[a-z&&[^bc]]

a z,除了 b c[ad-z](减去)

[a-z&&[^m-p]]

a z,而非 m p[a-lq-z](减去)

 

 

预定义字符类

.

任何字符(与行结束符可能匹配也可能不匹配)

/d

数字:[0-9]

/D

非数字: [^0-9]

/s

空白字符:[ /t/n/x0B/f/r], /t(tab)/n(new line)/r(return)

/S

非空白字符:[^/s]

/w

单词字符:[a-zA-Z_0-9]

/W

非单词字符:[^/w]

 

2.4         重复

指定重复的字符总是出现在它们所作用的模式之后。

Greedy 数量词

X?

X,一次或一次也没有

X*

X,零次或多次

X+

X,一次或多次

X{n}

X,恰好 n

X{n,}

X,至少 n

X{n,m}

X,至少 n 次,但是不超过 m

 

例如:

//s+java/s+ //match “java” with one or more spaces before and after

//d{2,4}/  // Match between two and four digits

2.5         选择、分组和引用

Logical 运算符

XY

X 后跟 Y

X|Y

X Y

(X)

X,作为捕获组

 

 

Back 引用

/n

任何匹配的 nth 捕获组

 

实例:/(ab|cd)+|ef)/ 匹配的既可以是字符串“ef”,也可以是字符串“ab”或者“cd”的一次或多次。

2.5.1.1       组和捕获

捕获组可以通过从左到右计算其开括号来编号。例如,在表达式 ((A)(B(C))) 中,存在四个这样的组:

1    

((A)(B(C)))

2    

/A

3    

(B(C))

4    

(C)

组零始终代表整个表达式。

之所以这样命名捕获组是因为在匹配中,保存了与这些组匹配的输入序列的每个子序列。捕获的子序列稍后可以通过 Back 引用在表达式中使用,也可以在匹配操作完成后从匹配器检索。

与组关联的捕获输入始终是与组最近匹配的子序列。如果由于量化的缘故再次计算了组,则在第二次计算失败时将保留其以前捕获的值(如果有的话)例如,将字符串 "aba" 与表达式 (a(b)?)+ 相匹配,会将第二组设置为 "b"。在每个匹配的开头,所有捕获的输入都会被丢弃。

(?) 开头的组是纯的非捕获 组,它不捕获文本,也不针对组合计进行计数。

2.6         行结束符

行结束符 是一个或两个字符的序列,标记输入字符序列的行结尾。以下代码被识别为行结束符:

  • 新行(换行)符 ('/n')
  • 后面紧跟新行符的回车符 ("/r/n")
  • 单独的回车符 ('/r')
  • 下一行字符 ('/u0085')
  • 行分隔符 ('/u2028')
  • 段落分隔符 ('/u2029)

2.7         边界匹配器(锚字符)

边界匹配器

^

行的开头

$

行的结尾

/b

单词边界

/B

非单词边界

/A

输入的开头

/G

上一个匹配的结尾

/Z

输入的结尾,仅用于最后的结束符(如果有的话)

/z

输入的结尾

例如:

2.8         标志

标志

i

执行一个不区分大小写的匹配

g

执行一个全局匹配。简而言之,即要找到所有的匹配,而不是找到第一个后就停止。

m

多行模式,^$ 除了匹配字符串的开头和结尾外还匹配每行的开头和结尾

 

例如:查找所有java//bjava/b/gi

3         Java正值表达式使用指南

3.1         介绍

正则表达式的编译表示形式。

指定为字符串的正则表达式必须首先被编译为此类的实例。然后,可将得到的模式用于创建 Matcher 对象,依照正则表达式,该对象可以与任意字符序列匹配。执行匹配所涉及的所有状态都驻留在匹配器中,所以多个匹配器可以共享同一模式。

因此,典型的调用顺序是

 Pattern p = Pattern.compile("a*b");
   
 Matcher m = p.matcher("aaaaab");
   
 boolean b = m.matches();
   

在仅使用一次正则表达式时,可以方便地通过此类定义 matches 方法。此方法编译表达式并在单个调用中将输入序列与其匹配。语句

 boolean b = Pattern.matches("a*b", "aaaaab");
   

等效于上面的三个语句,尽管对于重复的匹配而言它效率不高,因为它不允许重用已编译的模式

 

3.2         代码实例

3.2.1        典型调用顺序

  // 验证字符串是否为正整数或正小数

String regEx = "^[0-9]+//.?[0-9]*$";

       Pattern pattern = Pattern.compile(regEx);

       Matcher matcher = pattern.matcher(param);

       if(!matcher.find()){

           logger.debug(message + "必须为:正整数或正小数");

       }

 

3.2.2        split()函数

String text = "abcdebcadxbc";  String[] tokens = text.split(".bc");

        for(String token : tokens) {

            System.out.print(token + " ");

        }

输出:d ad

使用.bc来作比对,由于符合的子字符串有abcebcxbc 3个,所以split()方法会使用这3个字符串为依据来作字符串分离,返回的自然就是不符合表达式.bcdad

4         Javascript正值表达式使用指南

JavaScriptRegExp类表示正值表达式,而StringRegExp都定义了使用正值表达式进行强大模式匹配和文本检索与替换函数。

ECMAScript v3Javascript正值表达式进行了标准化。JavaScript 1.2实现了ECMAScript v3要求的正值表达式特性的子集,Javascript 1.5实现了完整的标准。

Javascript正值表达式完全以Perl程序语言的正值表达式为基础。

4.1         正则表达式在页面处理中的使用场景

l         表单验证。验证某些域符合某种规则,例如邮件输入框必须输入的是邮件、联系电话输入框输入的必须是数字等等

l         处理DOM模型。例如通过表达式定位DOM中的一个对象或一系列对象,一个例子就是定位id属性中含有某个特殊字符的div对象。

l         纯编程逻辑。直接用于编程的逻辑之中。

4.2         用于模式匹配的String方法

String支持四种利用正值表达式的方法,

最简单的search(),例如:”Javascirpt”.search(/script/i);

replace()进行检索和替换。例如:text.replace(/javacript/gi), “JavaScript”);

match是最常用的。” 1 plus 2 equals 3” .match(//d+/g) // 返回[“ 1” , “ 2” , “ 3” ]

split可以分解为字符串数组。例如:”1,2,  3,  4, 5” .split(//s*,/s*/); // returns [“ 1” ,” 2” ,” 3” ,” 4” , “ 5” ]

4.3         RegExp对象

无论是字符串直接量还是正值表达式都使用了字符/表示转义序列,所以必须用//替换所有的/字符。例如:var zipCode = new RegExp(“//d{5}”, “g”);

exec()方法在一个字符串中检索匹配。如果没有则返回null。例如:

var pattern = /Java/g;

var test = “JavaScript is more fun than Java!”;

var result;

while((reslut = pattern.exec(text)) != null) {

       alter(“mathed ‘” + result[0] + “’” + “at position “ + result.index + “;next search begins at “ + pattern.lastIndex);

}

 

test()比较简洁。

var pattern = /java/I;

pattern.test(“Javascript”); // return true

注意:只有带g标志的正值表达式才会发生这种特殊的lastIndex行为。如果没有gexec()test()将忽略它的lastIndex

5         常用的正则表达式

5.1         常用匹配内容

匹配中文字符的正则表达式: [/u4e00-/u9fa5] 评注:匹配中文还真是个头疼的事,有了这个表达式就好办了 匹配双字节字符(包括汉字在内)[^/x00-/xff] 评注:可以用来计算字符串的长度(一个双字节字符长度计2ASCII字符计1 匹配空白行的正则表达式:/n/s*/r 评注:可以用来删除空白行 匹配HTML标记的正则表达式:<(/S*?)[^>]*>.*?</>|<.*? /> 评注:网上流传的版本太糟糕,上面这个也仅仅能匹配部分,对于复杂的嵌套标记依旧无能为力 匹配首尾空白字符的正则表达式:^/s*|/s*$ 评注:可以用来删除行首行尾的空白字符(包括空格、制表符、换页符等等),非常有用的表达式 匹配Email地址的正则表达式:/w+([-+.]/w+)*@/w+([-.]/w+)*/./w+([-.]/w+)* 评注:表单验证时很实用 匹配网址URL的正则表达式:[a-zA-z]+://[^/s]* 评注:网上流传的版本功能很有限,上面这个基本可以满足需求 匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线)^[a-zA-Z][a-zA-Z0-9_]{4,15}$ 评注:表单验证时很实用 匹配国内电话号码:/d-/d|/d-/d 评注:匹配形式如 0511-4405222 021-87888822 匹配腾讯QQ号:[1-9][0-9]{4,} 评注:腾讯QQ号从10000开始 匹配中国邮政编码:[1-9]/d(?!/d) 评注:中国邮政编码为6位数字 匹配身份证:/d|/d 评注:中国的身份证为15位或18 匹配ip地址:/d+/./d+/./d+/./d+ 评注:提取ip地址时有用

 

5.2         判断数值类型

l         "^//d+$"  //非负整数(正整数   +   0    

l          "^[0-9]*[1-9][0-9]*$"  //正整数  包括:以0开头

l         /^/+?[1-9][0-9]*$/   //  正整数 不能以0开头

l            "^((-//d+)|(0+))$"  //非正整数(负整数   +   0   

l            "^-[0-9]*[1-9][0-9]*$"  //负整数    

l            "^-?//d+$"    //整数    

l            "^//d+(//.//d+)?$"  //非负浮点数(正浮点数   +   0    

l            "^(([0-9]+//.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*//.[0-9]+)|([0-9]*[1-9][0-9]*))$"  //正浮点数    

l            "^((-//d+(//.//d+)?)|(0+(//.0+)?))$"  //非正浮点数(负浮点数   +   0    

l           "^(-(([0-9]+//.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*//.[0-9]+)|([0-9]*[1-9][0-9]*)))$"  //负浮点数    

l            "^(-?//d+)(//.//d+)?$"  //浮点数

 

6         参考资料

1.      Javascript 权威指南》第5

2.       

你可能感兴趣的:(正值表达式使用指南)