使用正则表达式进行数据校验(java,javascript)

 
早期起源
正则表达式的“祖先”可以一直上溯至对人类神经系统如何工作的早期研究。Warren McCulloch 和 Walter Pitts 这两位神经生理学家研究出一种数学方式来描述这些神经网络。
1956 年, 一位叫 Stephen Kleene 的美国数学家在 McCulloch 和 Pitts 早期工作的基础上,发表了一篇标题为“神经网事件的表示法”的论文,引入了正则表达式的概念。正则表达式就是用来描述他称为“正则集的代数”的表达式,因此采用“正则表达式”这个术语。
随后,发现可以将这一工作应用于使用Ken Thompson 的计算搜索算法的一些早期研究,Ken Thompson是Unix 的主要发明人。正则表达式的第一个实用应用程序就是 Unix 中的 qed 编辑器。
使用正则表达式
在典型的搜索和替换操作中,必须提供要查找的确切文字。这种技术对于静态文本中的简单搜索和替换任务可能足够了,但是由于它缺乏灵活性,因此在搜索动态文本时就有困难了,甚至是不可能的。
使用正则表达式,就可以:
  • 测试字符串的某个模式。例如,可以对一个输入字符串进行测试,看在该字符串是否存在一个电话号码模式或一个信用卡号码模式。这称为数据有效性验证。
  • 替换文本。可以在文档中使用一个正则表达式来标识特定文字,然后可以全部将其删除,或者替换为别的文字。
  • 根据模式匹配从字符串中提取一个子字符串。可以用来在文本或输入字段中查找特定文字。
例如,如果需要搜索整个 web 站点来删除某些过时的材料并替换某些HTML 格式化标记,则可以使用正则表达式对每个文件进行测试,看在该文件中是否存在所要查找的材料或 HTML 格式化标记。用这个方法,就可以将受影响的文件范围缩小到包含要删除或更改的材料的那些文件。然后可以使用正则表达式来删除过时的材料,最后,可以再次使用正则表达式来查找并替换那些需要替换的标记。
正则表达式语法
一个正则表达式就是由普通字符(例如字符 a 到 z)以及特殊字符(称为元字符)组成的文字模式。该模式描述在查找文字主体时待匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。
这里有一些可能会遇到的正则表达式示例:
JavaScript
java
匹配
/^/[ /t]*$/
^//[ //t]*$
匹配一个空白行。
//d{2}-/d{5}/
   //d{2}-//d{5}
验证一个ID 号码是否由一个2位数字,一个连字符以及一个5位数字组成。
/<(.*)>.*<///1>/
 <(.*)>.*</1>
匹配一个 HTML 标记。
下表是元字符及其在正则表达式上下文中的行为的一个完整列表:
字符
描述
/
将下一个字符标记为一个特殊字符、或一个原义字符、或一个 后向引用、或一个八进制转义符。例如,'n' 匹配字符 "n"。'/n' 匹配一个换行符。序列 '//' 匹配 "/" 而 "/(" 则匹配 "("。
^
匹配输入字符串的开始位置。如果设置了 RegExp 对象的 Multiline 属性,^ 也匹配 '/n' 或 '/r' 之后的位置。
$
匹配输入字符串的结束位置。如果设置了RegExp 对象的 Multiline 属性,$ 也匹配 '/n' 或 '/r' 之前的位置。
*
匹配前面的子表达式零次或多次。例如,zo* 能匹配 "z" 以及 "zoo"。 * 等价于{0,}。
+
匹配前面的子表达式一次或多次。例如,'zo+' 能匹配 "zo" 以及 "zoo",但不能匹配 "z"。+ 等价于 {1,}。
?
匹配前面的子表达式零次或一次。例如,"do(es)?" 可以匹配 "do" 或 "does" 中的"do" 。? 等价于 {0,1}。
{n}
n 是一个非负整数。匹配确定的 n 次。例如,'o{2}' 不能匹配 "Bob" 中的 'o',但是能匹配 "food" 中的两个 o。
{n,}
n 是一个非负整数。至少匹配n 次。例如,'o{2,}' 不能匹配 "Bob" 中的 'o',但能匹配 "foooood" 中的所有 o。'o{1,}' 等价于 'o+'。'o{0,}' 则等价于 'o*'。
{n,m}
m n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。刘, "o{1,3}" 将匹配 "fooooood" 中的前三个 o。'o{0,1}' 等价于 'o?'。请注意在逗号和两个数之间不能有空格。
?
当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。例如,对于字符串 "oooo",'o+?' 将匹配单个 "o",而 'o+' 将匹配所有 'o'。
.
匹配除 "/n" 之外的任何单个字符。要匹配包括 '/n' 在内的任何字符,请使用象 '[./n]' 的模式。
(pattern)
匹配pattern 并获取这一匹配。所获取的匹配可以从产生的 Matches 集合得到,在VBScript 中使用 SubMatches 集合,在JScript 中则使用 $0$9 属性。要匹配圆括号字符,请使用 '/(' 或 '/)'。
(?:pattern)
匹配 pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。这在使用 "或" 字符 (|) 来组合一个模式的各个部分是很有用。例如, 'industr(?:y|ies) 就是一个比 'industry|industries' 更简略的表达式。
(?=pattern)
正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如, 'Windows (?=95|98|NT|2000)' 能匹配 "Windows 2000" 中的 "Windows" ,但不能匹配 "Windows 3.1" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始。
(?!pattern)
负向预查,在任何不匹配Negative lookahead matches the search string at any point where a string not matching pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。例如'Windows (?!95|98|NT|2000)' 能匹配 "Windows 3.1" 中的 "Windows",但不能匹配 "Windows 2000" 中的 "Windows"。预查不消耗字符,也就是说,在一个匹配发生后,在最后一次匹配之后立即开始下一次匹配的搜索,而不是从包含预查的字符之后开始
x |y
匹配 xy。例如,'z|food' 能匹配 "z" 或 "food"。'(z|f)ood' 则匹配 "zood" 或 "food"。
[xyz]
字符集合。匹配所包含的任意一个字符。例如, '[abc]' 可以匹配 "plain" 中的 'a'。
[^xyz]
负值字符集合。匹配未包含的任意字符。例如, '[^abc]' 可以匹配 "plain" 中的'p'。
[a-z]
字符范围。匹配指定范围内的任意字符。例如,'[a-z]' 可以匹配 'a' 到 'z' 范围内的任意小写字母字符。
[^a-z]
负值字符范围。匹配任何不在指定范围内的任意字符。例如,'[^a-z]' 可以匹配任何不在 'a' 到 'z' 范围内的任意字符。
/b
匹配一个单词边界,也就是指单词和空格间的位置。例如, 'er/b' 可以匹配"never" 中的 'er',但不能匹配 "verb" 中的 'er'。
/B
匹配非单词边界。'er/B' 能匹配 "verb" 中的 'er',但不能匹配 "never" 中的 'er'。
/cx
匹配由x指明的控制字符。例如, /cM 匹配一个 Control-M 或回车符。 x 的值必须为 A-Z 或 a-z 之一。否则,将 c 视为一个原义的 'c' 字符。
/d
匹配一个数字字符。等价于 [0-9]。
/D
匹配一个非数字字符。等价于 [^0-9]。
/f
匹配一个换页符。等价于 /x0c 和 /cL。
/n
匹配一个换行符。等价于 /x0a 和 /cJ。
/r
匹配一个回车符。等价于 /x0d 和 /cM。
/s
匹配任何空白字符,包括空格、制表符、换页符等等。等价于 [ /f/n/r/t/v]。
/S
匹配任何非空白字符。等价于 [^ /f/n/r/t/v]。
/t
匹配一个制表符。等价于 /x09 和 /cI。
/v
匹配一个垂直制表符。等价于 /x0b 和 /cK。
/w
匹配包括下划线的任何单词字符。等价于'[A-Za-z0-9_]'。
/W
匹配任何非单词字符。等价于 '[^A-Za-z0-9_]'。
/xn
匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。例如, '/x41' 匹配 "A"。'/x041' 则等价于 '/x04' & "1"。正则表达式中可以使用 ASCII 编码。.
/num
匹配 num,其中 num 是一个正整数。对所获取的匹配的引用。例如,'(.)/1' 匹配两个连续的相同字符。
/n
标识一个八进制转义值或一个后向引用。如果 /n 之前至少 n 个获取的子表达式,则 n 为后向引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。
/nm
标识一个八进制转义值或一个后向引用。如果 /nm 之前至少有is preceded by at least nm 个获取得子表达式,则 nm 为后向引用。如果 /nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的后向引用。如果前面的条件都不满足,若  nm 均为八进制数字 (0-7),则 /nm 将匹配八进制转义值 nm
/nml
如果 n 为八进制数字 (0-3),且 ml 均为八进制数字 (0-7),则匹配八进制转义值 nml。
/un
匹配 n,其中 n 是一个用四个十六进制数字表示的 Unicode 字符。例如, /u00A9 匹配版权符号 (?)。
建立正则表达式
构造正则表达式的方法和创建数学表达式的方法一样。也就是用多种元字符与操作符将小的表达式结合在一起来创建更大的表达式。
可以通过在一对分隔符之间放入表达式模式的各种组件来构造一个正则表达式。
JavaScript 而言,分隔符为一对正斜杠 (/) 字符。例如:
/expression/            注:expression为表达式
例如在JavaScript里面,定义正则表达式
var isuser=/^[/u4e00-/u9fa5]{2,5}$/;
 
对 Java 而言 ,则不需要分割符号(/),只需把它当成字符串来处理。
String regEx=“^[//u4e00-//u9fa5]{2,5}___FCKpd___5rdquo;;
 
注意:(除了这点,在Java中,你必须对每一个向前的斜杠(“/”)进行转义处理。我们要在每个“/”前面加上一个“/”以免出现编译错误。遗憾的是,转义处理过程很容易出现错误,所以应该小心谨慎。你可以首先输入未经转义处理的正则表达式,然后从左到右依次把每一个“/”替换成“//”。)
常用正则表达式举例
匹配中文字符的正则表达式: [/u4e00-/u9fa5]
评注:匹配中文还真是个头疼的事,有了这个表达式就好办了
―――――――――――――――――――――――――――――――――
匹配双字节字符(包括汉字在内):[^/x00-/xff]
评注:可以用来计算字符串的长度(一个双字节字符长度计2,ASCII字符计1)
―――――――――――――――――――――――――――――――――
匹配空白行的正则表达式:/n/s*/r
评注:可以用来删除空白行
―――――――――――――――――――――――――――――――――
匹配HTML标记的正则表达式:<(/S*?)[^>]*>.*?<//1>|<.*? />
评注:网上流传的版本太糟糕,上面这个也仅仅能匹配部分,对于复杂的嵌套标记依旧无能为力
―――――――――――――――――――――――――――――――――
匹配首尾空白字符的正则表达式:^/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{3}-/d{8}|/d{4}-/d{7}
评注:匹配形式如 0511-4405222 或 021-87888822
―――――――――――――――――――――――――――――――――
匹配腾讯QQ号:[1-9][0-9]{4,}
评注:腾讯QQ号从10000开始
―――――――――――――――――――――――――――――――――
匹配中国邮政编码:[1-9]/d{5}(?!/d)
评注:中国邮政编码为6位数字
―――――――――――――――――――――――――――――――――
匹配身份证:/d{15}|/d{18}
评注:中国的身份证为15位或18位
―――――――――――――――――――――――――――――――――
匹配ip地址:/d{1,3}/./d{1,3}/./d{1,3}/./d{1,3}
评注:提取ip地址时有用
―――――――――――――――――――――――――――――――――
匹配特定数字:
^[1-9]/d*$    //匹配正整数
^-[1-9]/d*$   //匹配负整数
^-?[1-9]/d*$   //匹配整数
^[1-9]/d*|0$  //匹配非负整数(正整数 + 0)
^-[1-9]/d*|0$   //匹配非正整数(负整数 + 0)
^[1-9]/d*/./d*|0/./d*[1-9]/d*$   //匹配正浮点数
^-([1-9]/d*/./d*|0/./d*[1-9]/d*)$  //匹配负浮点数
^-?([1-9]/d*/./d*|0/./d*[1-9]/d*|0?/.0+|0)$  //匹配浮点数
^[1-9]/d*/./d*|0/./d*[1-9]/d*|0?/.0+|0$   //匹配非负浮点数(正浮点数 + 0)
^(-([1-9]/d*/./d*|0/./d*[1-9]/d*))|0?/.0+|0$  //匹配非正浮点数(负浮点数 + 0)
评注:处理大量数据时有用,具体应用时注意修正
 
匹配特定字符串:
^[A-Za-z]+$  //匹配由26个英文字母组成的字符串
^[A-Z]+$  //匹配由26个英文字母的大写组成的字符串
^[a-z]+$  //匹配由26个英文字母的小写组成的字符串
^[A-Za-z0-9]+$  //匹配由数字和26个英文字母组成的字符串
^/w+$  //匹配由数字、26个英文字母或者下划线组成的字符串
完整例子
  在javascript中:
对于数据验证,应该在数据提交前进行验证,这就有两种方法
1 提交按钮的 onclick事件
2 表单的     onsubmit事件
 
  下面就举个例子test.jsp(onsubmit事件验证)
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="UTF-8"%>
<html>
    <head>
   
       <title> 测试正则表达式</title>
       <script>
       function check(){
      
            var isuser=/^[/u4e00-/u9fa5]{2,5}$/;      //2-5 个汉字
            var ispassword=/^/S{6,20}$/;              //6-20 个非空白字符
 
       document.mainform.username.value=document.mainform.username.value.replace(/(^/s*)|(/s*$)/g, "");            // 去掉前后空格
       document.mainform.password.value=document.mainform.password.value.replace(/(^/s*)|(/s*$)/g, "");            // 去掉前后空格
       var username=document.mainform.username.value;
       var password=document.mainform.password.value;
 
 
        if(!isuser.test(username)){
       alert(" 姓名必须是2-5个汉字!");
       mainform.username.focus();
       return false;
       }
       if(!ispassword.test(password)) {
       alert(" 密码格式不合法,请重新输入!");
       mainform.password.focus();
       return false;
    }
       }
      
       </script>
    </head>
    <body>
    <form name="mainform" method=post action="test.jsp" onSubmit="return check()">
    <tr><td><p>&nbsp;</p>
     <p> USERNAME
        <input name="username" type="text" maxlength="5">  
        </p></td></tr>
    <tr><td>&nbsp;</td>
    </tr>
    <p>
     PASSWORD
      <input name="password" type="password" maxlength="20">
      <input name="submit" type="submit" id=" 提交" value="submit" >
     </p>
    <tr> </tr>
    </form>
    </body>
</html>
 
在java中
与javascript相比,java就要比较麻烦一些。它需要先导入一个包(java.util.regex)。
java.util.regex 是一个用正则表达式所订制的模式来对字符串进行匹配工作的类库包。
它包括两个类:Pattern和Matcher Pattern (详细看后面附录)
Pattern 是一个正则表达式经编译后的表现模式。
一个Matcher对象是一个状态机器,它依据Pattern对象做为匹配模式对字符串展开匹配检查。
首先一个Pattern实例订制了一个所用语法与PERL的类似的正则表达式经编译后的模式,然后一个Matcher实例在这个给定的Pattern实例的模式控制下进行字符串的匹配工作。
例:(检测汉字)
import java.util.regex.*;
class Regex1{
 public static void main(String args[]) {
     
     String str=" 测试专用";
     String regEx="^[/u4e00-/u9fa5]{2,5}$";
     Pattern p=Pattern.compile(regEx);// 编译正则表达式
     Matcher m=p.matcher(str);// 生成一个给定命名的Matcher对象
     boolean result=m.find(); // 查找下一个匹配子串
     if(result){
       System.out.println(" 此为汉字");
     }
     else{
      System.out.println(" 不是汉字");
     }
     
    }
}
附录
以下我们就分别来看看java.util.regex包里面的这两个类:
Pattern : (Pattern 的方法如下:)
(1)static Pattern compile(String regex)
将给定的正则表达式编译并赋予给Pattern类
      例:Pattern p = Pattern.compile("[/]+");
(2)static Pattern compile(String regex, int flags)
同上,但增加flag参数的指定,可选的flag参数包括:CASE INSENSITIVE,MULTILINE,DOTALL,UNICODE CASE, CANON EQ
返回当前Pattern的匹配flag参数.
(3)Matcher matcher(CharSequence input)
生成一个给定命名的Matcher对象
(4)static boolean matches(String regex, CharSequence input)
编译给定的正则表达式并且对输入的字串以该正则表达式为模开展匹配,该方法适合于该正则表达式只会使用一次的情况,也就是只进行一次匹配工作,因为这种情况下并不需要生成一个Matcher实例。
(5)String pattern()
返回该Patter对象所编译的正则表达式。
(6)String[] split(CharSequence input)
将目标字符串按照Pattern里所包含的正则表达式为模进行分割。
(7)String[] split(CharSequence input, int limit)
作用同上,增加参数limit目的在于要指定分割的段数,如将limi设为2,那么目标字符串将根据正则表达式分为割为两段。

一个正则表达式,也就是一串有特定意义的字符,必须首先要编译成为一个Pattern类的实例,这个Pattern对象将会使用matcher()方法来生成一个Matcher实例,接着便可以使用该 Matcher实例以编译的正则表达式为基础对目标字符串进行匹配工作,多个Matcher是可以共用一个Pattern对象的。

现在我们先来看一个简单的例子,再通过分析它来了解怎样生成一个Pattern对象并且编译一个正则表达式,最后根据这个正则表达式将目标字符串进行分割:
import java.util.regex.*;
public class Replacement{
public static void main(String[] args) throws Exception {
         //
生成一个Pattern,同时编译一个正则表达式
Pattern p = Pattern.compile("[/]+");
         //用Pattern的split()方法把字符串按"/"分割
String[] result = p.split(
"Kevin has seen《LEON》seveal times,because it is a good film."
+"/ 凯文已经看过《这个杀手不太冷》几次了,因为它是一部"
+"好电影。/名词:凯文。");
for (int i=0; i<result.length; i++)
System.out.println(result[i]);
}
}

输出结果为:
Kevin has seen《 LEON》seveal times,because it is a good film.
凯文已经看过《这个杀手不太冷》几次了,因为它是一部好电影。
名词:凯文。

很明显,该程序将字符串按"/"进行了分段,我们以下再使用 split(CharSequence input, int limit)方法来指定分段的段数,程序改动为:
tring[] result = p.split("Kevin has seen《LEON》seveal times,because it is a good film./ 凯文已经看过《这个杀手不太冷》几次了,因为它是一部好电影。/名词:凯文。",2);
这里面的参数"2"表明将目标语句分为两段。
输出结果则为:
Kevin has seen《 LEON》seveal times,because it is a good film.
凯文已经看过《这个杀手不太冷》几次了,因为它是一部好电影。/名词:凯文。

但是在java.util.regex包里,我们经常仅需生成Pattern类,直接使用它的compile()方法,然后配合Matcher使用。
Pattern p = Pattern.compile("[/]+");
Matcher类:
(Matcher方法如下)
(1) Matcher appendReplacement(StringBuffer sb, String replacement)
    
将当前匹配子串替换为指定字符串,并且将替换后的子串以及其之前到上次 匹配子串之后的字符串段添加到一个StringBuffer对象里。
(2)StringBuffer appendTail(StringBuffer sb)
    将最后一次匹配工作后剩余的字符串添加到一个StringBuffer对象里。
(3)int end()
    返回当前匹配的子串的最后一个字符在原目标字符串中的索引位置 。
(4)int end(int group)
    返回与匹配模式里指定的组相匹配的子串最后一个字符的位置。
(5)boolean find()
    尝试在目标字符串里查找下一个匹配子串。
(6)boolean find(int start)
    重设Matcher对象,并且尝试在目标字符串里从指定的位置开始查找下一个匹配的子串。
(7)String group()
    返回当前查找而获得的与组匹配的所有子串内容
(8)String group(int group)
    返回当前查找而获得的与指定的组匹配的子串内容
(9)int groupCount()
    返回当前查找所获得的匹配组的数量。
(10)boolean lookingAt()
    检测目标字符串是否以匹配的子串起始。
(11)boolean matches()
    尝试对整个目标字符展开匹配检测,也就是只有整个目标字符串完全匹配时才返回真值。
(12)Pattern pattern()
    返回该Matcher对象的现有匹配模式,也就是对应的Pattern 对象。
(13)String replaceAll(String replacement)
    将目标字符串里与既有模式相匹配的子串全部替换为指定的字符串。
(14)String replaceFirst(String replacement)
    将目标字符串里第一个与既有模式相匹配的子串替换为指定的字符串。
(15)Matcher reset()
    重设该Matcher对象。
(16)Matcher reset(CharSequence input)
    重设该Matcher对象并且指定一个新的目标字符串。
(17)int start()
返回当前查找所获子串的开始字符在原目标字符串中的位置。
(18)int start(int group)
返回当前查找所获得的和指定组匹配的子串的第一个字符在原目标字符串中的位置。
我们分别来看看各方法的使用:

matches()/lookingAt ()/find()
一个Matcher对象是由一个Pattern对象调用其matcher()方法而生成的,一旦该Matcher对象生成,它就可以进行三种不同的匹配查找操作:

matches()方法尝试对整个目标字符展开匹配检测,也就是只有整个目标字符串完全匹配时才返回真值。
lookingAt ()方法将检测目标字符串是否以匹配的子串起始。
find()方法尝试在目标字符串里查找下一个匹配子串。

以上三个方法都将返回一个布尔值来表明成功与否。

replaceAll ()/appendReplacement()/appendTail()
Matcher类同时提供了四个将匹配子串替换成指定字符串的方法:

replaceAll()
replaceFirst()
appendReplacement()
appendTail()

replaceAll()与replaceFirst()的用法都比较简单,请看上面方法的解释。我们主要重点了解一下appendReplacement()和appendTail()方法。

appendReplacement(StringBuffer sb, String replacement) 将当前匹配子串替换为指定字符串,并且将替换后的子串以及其之前到上次匹配子串之后的字符串段添加到一个StringBuffer对象里,而appendTail(StringBuffer sb) 方法则将最后一次匹配工作后剩余的字符串添加到一个StringBuffer对象里。

例如,有字符串fatcatfatcatfat,假设既有正则表达式模式为"cat",第一次匹配后调用appendReplacement(sb,"dog"),那么这时StringBuffer sb的内容为fatdog,也就是fatcat中的cat被替换为dog并且与匹配子串前的内容加到sb里,而第二次匹配后调用appendReplacement(sb,"dog"),那么sb的内容就变为fatdogfatdog,如果最后再调用一次appendTail(sb),那么sb最终的内容将是fatdogfatdogfat。

我们来看个简单的程序:
//该例将把句子里的"Kelvin"改为"Kevin"
import java.util.regex.*;
public class MatcherTest{
public static void main(String[] args)
throws Exception {
//
生成Pattern对象并且编译一个简单的正则表达式"Kelvin"
Pattern p = Pattern.compile("Kelvin");
//用Pattern类的matcher()方法生成一个Matcher对象
Matcher m = p.matcher("Kelvin Li and Kelvin Chan are both working in Kelvin Chen's KelvinSoftShop company");
StringBuffer sb = new StringBuffer();
int i=0;
   //使用find()方法查找第一个匹配的对象
boolean result = m.find();
   //使用循环将句子里所有的kelvin找出并替换再将内容加到sb里
while(result) {
i++;
m.appendReplacement(sb, "Kevin");
System.out.println("第"+i+"次匹配后sb的内容是:"+sb);
   //继续查找下一个匹配对象
result = m.find();
}
    //最后调用appendTail()方法将最后一次匹配后的剩余字符串加到sb里;
m.appendTail(sb);
System.out.println("调用m.appendTail(sb)后sb的最终内容是:"+ sb.toString());
}
}

最终输出结果为:
第1次匹配后sb的内容是:Kevin
第2次匹配后sb的内容是:Kevin Li and Kevin
第3次匹配后sb的内容是:Kevin Li and Kevin Chan are both working in Kevin
第4次匹配后sb的内容是:Kevin Li and Kevin Chan are both working in Kevin Chen's Kevin
调用m.appendTail(sb)后sb的最终内容是:Kevin Li and Kevin Chan are both working in Kevin Chen's KevinSoftShop company.

group()/group(int group)/groupCount()

该系列方法与我们在上篇介绍的Jakarta-ORO中的MatchResult .group()方法类似(有关Jakarta-ORO请参考上篇的内容),都是要返回与组匹配的子串内容,下面代码将很好解释其用法:
import java.util.regex.*;
 
public class GroupTest{
public static void main(String[] args)
throws Exception {
Pattern p = Pattern.compile("(ca)(t)");
Matcher m = p.matcher("one cat,two cats in the yard");
StringBuffer sb = new StringBuffer();
boolean result = m.find();
System.out.println(" 该次查找获得匹配组的数量为:"+m.groupCount());
for(int i=1;i<=m.groupCount();i++){
    System.out.println(" 第"+i+"组的子串内容为:"+m.group(i));
}
 
}
}
输出为:
该次查找获得匹配组的数量为:2
第1组的子串内容为:ca
第2组的子串内容为:t


 
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
您可以按照以下步骤来完成使用Apache DBUtils(JDBC)+Servlet+JSP+EL+JSTL+HTML+CSS+JavaScript(jQuery)对animal表进行增删改查操作: 1. 创建数据库表animal,字段如下: - `aid int(5) 自增 主键`:动物编号 - `aname varchar(10) 非空`:动物名称 - `asex varchar(5) 非空`:性别 - `abirthday date 非空`:出生日期 2. 创建Java类Animal,对应animal表的实体类。在Animal类中定义与animal表字段对应的属性、构造方法、getter和setter方法。 3. 创建AnimalDAO类,用于执行与数据库交互的操作,包括增删改查。 4. 创建AnimalServlet类,处理前端页面的请求,并调用AnimalDAO类的方法进行数据库操作。 5. 创建JSP页面,包括增删改查的页面。使用EL表达式和JSTL标签库来展示数据。 6. 在HTML页面中使用JavaScript和jQuery来完成前端的点击事件,触发相应的操作。 7. 在前端页面中使用正则表达式进行数据校验,确保填写的数据符合要求。 8. 在AnimalServlet类中实现分页功能,通过传递参数来控制每页显示的数据量。 9. 运行项目,并录制演示视频,展示增删改查的效果。将录屏视频和所有代码提交。 请注意,以上是一个概要的步骤,具体的实现过程和代码编写会有更多细节。在实际开发中,您可能还需要配置数据库连接、导入相关依赖库等操作。希望这个概要能够帮助到您,如果有任何问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值