正则表达式(Java)[精]

正则表达式(Java)[精]
正则表达式(Java)[精]

正则表达式

正则表达式是JDK 1.4的新功能,但是对sed和awk这样的Unix的标准实用工具,以及Python,Perl之类的语言来讲,它早就已经成为其不可或缺的组成部分了(有人甚至认为,它还是Perl能大获成功的最主要的原因)。单从技术角度来讲,正则表达式只是一种处理字符串的工具(过去Java这个任务是交由String,StringBuffer以及StringTokenizer处理的),但是它常常和I/O一起使用,所以放到这里来讲也不算太离题吧。

正则表达式是一种功能强大但又非常灵活的文本处理工具。它能让你用编程的方式来描述复杂的文本模式,然后在字符串里把它找出来。一旦你找到了这种模式,你就能随心所欲地处理这些文本了。虽然初看起来正则表达式的语法有点让人望而生畏,但它提供了一种精练的动态语言,使我们能用一种通用的方式来解决各种字符串的问题,包括匹配,选择,编辑以及校验。

创建正则表达式

你可以从比较简单的东西入手学习正则表达式。要想全面地掌握怎样构建正则表达式,可以去看JDK 文档的java.util.regex的Pattern类的文档。

正则表达式的强大体现在它能定义字符集(character class)。下面是一些最常见的字符集及其定义的方式,此外还有一些预定义的字符集:

如果你用过其它语言的正则表达式,那么你一眼就能看出反斜杠的与众不同。在其它语言里,"\"的意思是:“只是要在正则表达式里插入一个反斜杠。没什么特别的意思。”但是在Java里,"\"的意思是:“要插入一个正则表达式的反斜杠,所以跟在它后面的那个字符的意思就变了。”举例来说,如果你想表示一个或更多的"单词字符",那么这个正则表达式就应该是"\w+"。如果你要插入一个反斜杠,那就得用"\\"。不过像换行,跳格之类的还是只用一根反斜杠:"\n\t"。

这里只给你讲一个例子;你应该JDK文档的java.util.regex.Pattern加到收藏夹里,这样就能很容易地找到各种正则表达式的模式了。

举一个具体一些的例子。下面这些正则表达式都是合法的,而且都能匹配"Rudolph":

Rudolph

[rR]udolph

[rR][aeiou][a-z]ol.*

R.*

数量表示符

数量表示符(quantifier)的作用是定义模式应该匹配多少个字符。

?Greedy(贪婪的):

除非另有表示,否则数量表示符都是greedy的。Greedy的表达式会一直匹配下去,直到匹配不下去为止。(如果你发现表达式匹配的结果与预期的不符),很有可能是因为,你以为表达式会只匹配前面几个字符,而实际上它是greedy的,因此会一直匹配下去。

?Reluctant(勉强的):

用问号表示,它会匹配最少的字符。也称为lazy, minimal matching, non-greedy, 或ungreedy。

Possessive(占有的):

目前只有Java支持(其它语言都不支持)。它更加先进,所以你可能还不太会用。用正则表达式匹配字符串的时候会产生很多中间状态,(一般的匹配引擎会保存这种中间状态,)这样匹配失败的时候就能原路返回了。占有型的表达式不保存这种中间状态,因此也就不会回头重来了。它能防止正则表达式的失控,同时也能提高运行的效率。

再提醒一下,要想让表达式照你的意思去运行,你应该用括号把'X'括起来。比方说:

abc+

似乎这个表达式能匹配一个或若干个'abc',但是如果你真的用它去匹配'abcabcabc'的话,实际上只会找到三个字符。因为这个表达式的意思是'ab'后边跟着一个或多个'c'。要想匹配一个或多个完整的'abc',你应该这样:

(abc)+

正则表达式能轻而易举地把你给耍了;这是一种建立在Java之上的新语言。

CharSequence

JDK 1.4定义了一个新的接口,叫CharSequence。它提供了String和StringBuffer这两个类的字符序列的抽象:

interface CharSequence {

charAt(int i);

length();

subSequence(int start, int end);

toString();

}

为了实现这个新的CharSequence接口,String,StringBuffer以及CharBuffer都作了修改。很多正则表达式的操作都要拿CharSequence作参数。

Pattern和Matcher

先给一个例子。下面这段程序可以测试正则表达式是否匹配字符串。第一个参数是要匹配的字符串,后面是正则表达式。正则表达式可以有多个。在Unix/Linux环境下,命令行下的正则表达式还必须用引号。

当你创建正则表达式时,可以用这个程序来判断它是不是会按照你的要求工作。

//: c12:TestRegularExpression.java

// Allows you to easly try out regular expressions.

// {Args: abcabcabcdefabc "abc+" "(abc)+" "(abc){2,}" }

import java.util.regex.*;

public class TestRegularExpression {

public static void main(String[] args) {

if(args.length < 2) {

System.out.println("Usage:\n" +

"java TestRegularExpression " +

"characterSequence regularExpression+");

System.exit(0);

}

System.out.println("Input: \"" + args[0] + "\"");

for(int i = 1; i < args.length; i++) {

System.out.println(

"Regular expression: \"" + args[i] + "\"");

Pattern p = https://www.360docs.net/doc/0e2884490.html,pile(args[i]);

Matcher m = p.matcher(args[0]);

while(m.find()) {

System.out.println("Match \"" + m.group() +

"\" at positions " +

m.start() + "-" + (m.end() - 1));

}

}

}

} ///:~

Java的正则表达式是由java.util.regex的Pattern和Matcher类实现的。Pattern对象表示经编译的正则表达式。静态的compile( )方法负责将表示正则表达式的字符串编译成Pattern对象。正如上述例程所示的,只要给Pattern的matcher( )方法送一个字符串就能获取一个Matcher对象。此外,Pattern还有一个能快速判断能否在input里面找到regex的(注意,原文有误,漏了方法名)

static boolean matches( regex, input)

以及能返回String数组的split( )方法,它能用regex把字符串分割开来。

只要给Pattern.matcher( )方法传一个字符串就能获得Matcher对象了。接下来就能用Matcher的方法来查询匹配的结果了。

boolean matches()

boolean lookingAt()

boolean find()

boolean find(int start)

matches( )的前提是Pattern匹配整个字符串,而lookingAt( )的意思是Pattern匹配字符串的开头。

find( )的功能是发现CharSequence里的,与pattern相匹配的多个字符序列。例如:

//: c12:FindDemo.java

import java.util.regex.*;

import com.bruceeckel.simpletest.*;

import java.util.*;

public class FindDemo {

private static Test monitor = new Test();

public static void main(String[] args) {

Matcher m = https://www.360docs.net/doc/0e2884490.html,pile("\\w+")

.matcher("Evening is full of the linnet's wings");

while(m.find())

System.out.println(m.group());

int i = 0;

while(m.find(i)) {

System.out.print(m.group() + " ");

i++;

}

monitor.expect(new String[] {

"Evening",

"is",

"full",

"of",

"the",

"linnet",

"s",

"wings",

"Evening vening ening ning ing ng g is is s full " +

"full ull ll l of of f the the he e linnet linnet " +

"innet nnet net et t s s wings wings ings ngs gs s "

});

}

} ///:~

"\\w+"的意思是"一个或多个单词字符",因此它会将字符串直接分解成单词。find( )像一个迭代器,从头到尾扫描一遍字符串。第二个find( )是带int参数的,正如你所看到的,它会告诉方法从哪里开始找——即从参数位置开始查找。

Groups

Group是指里用括号括起来的,能被后面的表达式调用的正则表达式。Group 0 表示整个表达式,group 1表示第一个被括起来的group,以此类推。所以:

A(B(C))D

里面有三个group:group 0是ABCD,group 1是BC,group 2是C。

你可以用下述Matcher方法来使用group:

public int groupCount( ) :返回matcher对象中的group的数目。不包括group0。

public String group( ) :返回上次匹配操作(比方说find( ))的group 0(整个匹配)

public String group(int i) :返回上次匹配操作的某个group。如果匹配成功,但是没能找到group,则

返回null。

public int start(int group) :返回上次匹配所找到的,group的开始位置。

public int end(int group) :返回上次匹配所找到的,group的结束位置,最后一个字符的下标加一。下面我们举一些group的例子:

//: c12:Groups.java

import java.util.regex.*;

import com.bruceeckel.simpletest.*;

public class Groups {

private static Test monitor = new Test();

static public final String poem =

"Twas brillig, and the slithy toves\n" +

"Did gyre and gimble in the wabe.\n" +

"All mimsy were the borogoves,\n" +

"And the mome raths outgrabe.\n\n" +

"Beware the Jabberwock, my son,\n" +

"The jaws that bite, the claws that catch.\n" +

"Beware the Jubjub bird, and shun\n" +

"The frumious Bandersnatch.";

public static void main(String[] args) {

Matcher m =

https://www.360docs.net/doc/0e2884490.html,pile("(?m)(\\S+)\\s+((\\S+)\\s+(\\S+))$")

.matcher(poem);

while(m.find()) {

for(int j = 0; j <= m.groupCount(); j++)

System.out.print("[" + m.group(j) + "]");

System.out.println();

}

monitor.expect(new String[]{

"[the slithy toves]" +

"[the][slithy toves][slithy][toves]",

"[in the wabe.][in][the wabe.][the][wabe.]",

"[were the borogoves,]" +

"[were][the borogoves,][the][borogoves,]",

"[mome raths outgrabe.]" +

"[mome][raths outgrabe.][raths][outgrabe.]",

"[Jabberwock, my son,]" +

"[Jabberwock,][my son,][my][son,]",

"[claws that catch.]" +

"[claws][that catch.][that][catch.]",

"[bird, and shun][bird,][and shun][and][shun]",

"[The frumious Bandersnatch.][The]" +

"[frumious Bandersnatch.][frumious][Bandersnatch.]"

});

}

} ///:~

这首诗是Through the Looking Glass的,Lewis Carroll的"Jabberwocky"的第一部分。可以看到这个正则表达式里有很多用括号括起来的group,它是由任意多个连续的非空字符('\S+')和任意多个连续的空格字符('\s+')所组成的,其最终目的是要捕获每行的最后三个单词;'$'表示一行的结尾。但是'$'通常表示整个字符串的结尾,所以这里要明确地告诉正则表达式注意换行符。这一点是由'(?m)'标志完成的(模式标志会过一会讲解)。

start( )和end( )

如果匹配成功,start( )会返回此次匹配的开始位置,end( )会返回此次匹配的结束位置,即最后一个字符的下标加一。如果之前的匹配不成功(或者没匹配),那么无论是调用start( )还是end( ),都会引发一个IllegalStateException。下面这段程序还演示了matches( )和lookingAt( ):

//: c12:StartEnd.java

import java.util.regex.*;

import com.bruceeckel.simpletest.*;

public class StartEnd {

private static Test monitor = new Test();

public static void main(String[] args) {

String[] input = new String[] {

"Java has regular expressions in 1.4",

"regular expressions now expressing in Java",

"Java represses oracular expressions"

};

Pattern

p1 = https://www.360docs.net/doc/0e2884490.html,pile("re\\w*"),

p2 = https://www.360docs.net/doc/0e2884490.html,pile("Java.*");

for(int i = 0; i < input.length; i++) {

System.out.println("input " + i + ": " + input[i]);

Matcher

m1 = p1.matcher(input[i]),

m2 = p2.matcher(input[i]);

while(m1.find())

System.out.println("m1.find() '" + m1.group() +

"' start = "+ m1.start() + " end = " + m1.end());

while(m2.find())

System.out.println("m2.find() '" + m2.group() + "' start = "+ m2.start() + " end = " + m2.end());

if(m1.lookingAt()) // No reset() necessary

System.out.println("m1.lookingAt() start = "

+ m1.start() + " end = " + m1.end());

if(m2.lookingAt())

System.out.println("m2.lookingAt() start = "

+ m2.start() + " end = " + m2.end());

if(m1.matches()) // No reset() necessary

System.out.println("m1.matches() start = "

+ m1.start() + " end = " + m1.end());

if(m2.matches())

System.out.println("m2.matches() start = "

+ m2.start() + " end = " + m2.end());

}

monitor.expect(new String[] {

"input 0: Java has regular expressions in 1.4",

"m1.find() 'regular' start = 9 end = 16",

"m1.find() 'ressions' start = 20 end = 28",

"m2.find() 'Java has regular expressions in 1.4'" +

" start = 0 end = 35",

"m2.lookingAt() start = 0 end = 35",

"m2.matches() start = 0 end = 35",

"input 1: regular expressions now " +

"expressing in Java",

"m1.find() 'regular' start = 0 end = 7",

"m1.find() 'ressions' start = 11 end = 19",

"m1.find() 'ressing' start = 27 end = 34",

"m2.find() 'Java' start = 38 end = 42",

"m1.lookingAt() start = 0 end = 7",

"input 2: Java represses oracular expressions",

"m1.find() 'represses' start = 5 end = 14",

"m1.find() 'ressions' start = 27 end = 35",

"m2.find() 'Java represses oracular expressions' " +

"start = 0 end = 35",

"m2.lookingAt() start = 0 end = 35",

"m2.matches() start = 0 end = 35"

});

}

} ///:~

注意,只要字符串里有这个模式,find( )就能把它给找出来,但是lookingAt( )和matches( ),只有在字符串与正则表达式一开始就相匹配的情况下才能返回true。matches( )成功的前提是正则表达式与字符串完全匹配,而lookingAt( )[67]成功的前提是,字符串的开始部分与正则表达式相匹配。

匹配的模式(Pattern flags)

compile( )方法还有一个版本,它需要一个控制正则表达式的匹配行为的参数:

Pattern https://www.360docs.net/doc/0e2884490.html,pile(String regex, int flag)

flag的取值范围如下:

在这些标志里面,Pattern.CASE_INSENSITIVE,Pattern.MULTILINE,以及https://www.360docs.net/doc/0e2884490.html,MENTS 是最有用的(其中https://www.360docs.net/doc/0e2884490.html,MENTS还能帮我们把思路理清楚,并且/或者做文档)。注意,你可以用在表达式里插记号的方式来启用绝大多数的模式。这些记号就在上面那张表的各个标志的下面。你希望模式从哪里开始启动,就在哪里插记号。

可以用"OR" ('|')运算符把这些标志合使用:

//: c12:ReFlags.java

import java.util.regex.*;

import com.bruceeckel.simpletest.*;

public class ReFlags {

private static Test monitor = new Test();

public static void main(String[] args) {

Pattern p = https://www.360docs.net/doc/0e2884490.html,pile("^java",

Pattern.CASE_INSENSITIVE | Pattern.MULTILINE);

Matcher m = p.matcher(

"java has regex\nJava has regex\n" +

"JAVA has pretty good regular expressions\n" +

"Regular expressions are in Java");

while(m.find())

System.out.println(m.group());

monitor.expect(new String[] {

"java",

"Java",

"JAVA"

});

}

} ///:~

这样创建出来的正则表达式就能匹配以"java","Java","JAVA"...开头的字符串了。此外,如果字符串分好几行,那它还会对每一行做匹配(匹配始于字符序列的开始,终于字符序列当中的行结束符)。注意,group( )方法仅返回匹配的部分。

split( )

所谓分割是指将以正则表达式为界,将字符串分割成String数组。

String[] split(CharSequence charseq)

String[] split(CharSequence charseq, int limit)

这是一种既快又方便地将文本根据一些常见的边界标志分割开来的方法。

//: c12:SplitDemo.java

import java.util.regex.*;

import com.bruceeckel.simpletest.*;

import java.util.*;

public class SplitDemo {

private static Test monitor = new Test();

public static void main(String[] args) {

String input =

"This!!unusual use!!of exclamation!!points";

System.out.println(Arrays.asList(

https://www.360docs.net/doc/0e2884490.html,pile("!!").split(input)));

// Only do the first three:

System.out.println(Arrays.asList(

https://www.360docs.net/doc/0e2884490.html,pile("!!").split(input, 3)));

System.out.println(Arrays.asList(

"Aha! String has a split() built in!".split(" ")));

monitor.expect(new String[] {

"[This, unusual use, of exclamation, points]",

"[This, unusual use, of exclamation!!points]",

"[Aha!, String, has, a, split(), built, in!]"

});

}

} ///:~

第二个split( )会限定分割的次数。

正则表达式是如此重要,以至于有些功能被加进了String类,其中包括split( )(已经看到了),matches( ),replaceFirst( )以及replaceAll( )。这些方法的功能同Pattern和Matcher的相同。

替换操作

正则表达式在替换文本方面特别在行。下面就是一些方法:

replaceFirst(String replacement):

将字符串里,第一个与模式相匹配的子串替换成replacement。

replaceAll(String replacement):

将输入字符串里所有与模式相匹配的子串全部替换成replacement。

appendReplacement(StringBuffer sbuf, String replacement):

对sbuf进行逐次替换,而不是像replaceFirst( )或replaceAll( )那样,只替换第一个或全部子串。这是个非常重要的方法,因为它可以调用方法来生成replacement(replaceFirst( )和replaceAll( )只允许用固定的字符串来充当replacement)。有了这个方法,你就可以编程区分group,从而实现更强大的替换功能。

调用完appendReplacement( )之后,为了把剩余的字符串拷贝回去,必须调用appendTail(StringB uffer sbuf, String replacement)。

下面我们来演示一下怎样使用这些替换方法。说明一下,这段程序所处理的字符串是它自己开头部分的注释,是用正则表达式提取出来并加以处理之后再传给替换方法的。

//: c12:TheReplacements.java

import java.util.regex.*;

import java.io.*;

import com.bruceeckel.util.*;

import com.bruceeckel.simpletest.*;

/*! Here's a block of text to use as input to

the regular expression matcher. Note that we'll

first extract the block of text by looking for

the special delimiters, then process the

extracted block. !*/

public class TheReplacements {

private static Test monitor = new Test();

public static void main(String[] args) throws Exception {

String s = TextFile.read("TheReplacements.java");

// Match the specially-commented block of text above:

Matcher mInput =

https://www.360docs.net/doc/0e2884490.html,pile("/\\*!(.*)!\\*/", Pattern.DOTALL)

.matcher(s);

if(mInput.find())

s = mInput.group(1); // Captured by parentheses

// Replace two or more spaces with a single space:

s = s.replaceAll(" {2,}", " ");

// Replace one or more spaces at the beginning of each

// line with no spaces. Must enable MULTILINE mode:

s = s.replaceAll("(?m)^ +", "");

System.out.println(s);

s = s.replaceFirst("[aeiou]", "(VOWEL1)");

StringBuffer sbuf = new StringBuffer();

Pattern p = https://www.360docs.net/doc/0e2884490.html,pile("[aeiou]");

Matcher m = p.matcher(s);

// Process the find information as you

// perform the replacements:

while(m.find())

m.appendReplacement(sbuf, m.group().toUpperCase());

// Put in the remainder of the text:

m.appendTail(sbuf);

System.out.println(sbuf);

monitor.expect(new String[]{

"Here's a block of text to use as input to",

"the regular expression matcher. Note that we'll",

"first extract the block of text by looking for",

"the special delimiters, then process the",

"extracted block. ",

"H(VOWEL1)rE's A blOck Of tExt tO UsE As InpUt tO",

"thE rEgUlAr ExprEssIOn mAtchEr. NOtE thAt wE'll",

"fIrst ExtrAct thE blOck Of tExt by lOOkIng fOr",

"thE spEcIAl dElImItErs, thEn prOcEss thE",

"ExtrActEd blOck. "

});

}

} ///:~

我们用前面介绍的TextFile.read( )方法来打开和读取文件。mInput的功能是匹配'/*!' 和'!*/' 之间的文本(注意一下分组用的括号)。接下来,我们将所有两个以上的连续空格全都替换成一个,并且将各行开头的空格全都去掉(为了让这个正则表达式能对所有的行,而不仅仅是第一行起作用,必须启用多行模式)。

这两个操作都用了String的replaceAll( )(这里用它更方便)。注意,由于每个替换只做一次,因此除了预编译Pattern之外,程序没有额外的开销。

replaceFirst( )只替换第一个子串。此外,replaceFirst( )和replaceAll( )只能用常量(literal)来替换,所以如果你每次替换的时候还要进行一些操作的话,它们是无能为力的。碰到这种情况,你得用appendReplacement( ),它能让你在进行替换的时候想写多少代码就写多少。在上面那段程序里,创建sbuf 的过程就是选group做处理,也就是用正则表达式把元音字母找出来,然后换成大写的过程。通常你得在完成全部的替换之后才调用appendTail( ),但是如果要模仿replaceFirst( )(或"replace n")的效果,你也可以只替换一次就调用appendTail( )。它会把剩下的东西全都放进sbuf。

你还可以在appendReplacement( )的replacement参数里用"$g"引用已捕获的group,其中'g' 表示group的号码。不过这是为一些比较简单的操作准备的,因而其效果无法与上述程序相比。

reset( )

此外,还可以用reset( )方法给现有的Matcher对象配上个新的CharSequence。

//: c12:Resetting.java

import java.util.regex.*;

import java.io.*;

import com.bruceeckel.simpletest.*;

public class Resetting {

private static Test monitor = new Test();

public static void main(String[] args) throws Exception {

Matcher m = https://www.360docs.net/doc/0e2884490.html,pile("[frb][aiu][gx]")

.matcher("fix the rug with bags");

while(m.find())

System.out.println(m.group());

m.reset("fix the rig with rags");

while(m.find())

System.out.println(m.group());

monitor.expect(new String[]{

"fix",

"rug",

"bag",

"fix",

"rig",

"rag"

});

}

} ///:~

如果不给参数,reset( )会把Matcher设到当前字符串的开始处。

正则表达式与Java I/O

到目前为止,你看到的都是用正则表达式处理静态字符串的例子。下面我们来演示一下怎样用正则表达式扫描文件并且找出匹配的字符串。受Unix的grep启发,我写了个JGrep.java,它需要两个参数:文

件名,以及匹配字符串用的正则表达式。它会把匹配这个正则表达式那部分内容及其所属行的行号打印出来。

//: c12:JGrep.java

// A very simple version of the "grep" program.

// {Args: JGrep.java "\\b[Ssct]\\w+"}

import java.io.*;

import java.util.regex.*;

import java.util.*;

import com.bruceeckel.util.*;

public class JGrep {

public static void main(String[] args) throws Exception {

if(args.length < 2) {

System.out.println("Usage: java JGrep file regex");

System.exit(0);

}

Pattern p = https://www.360docs.net/doc/0e2884490.html,pile(args[1]);

// Iterate through the lines of the input file:

ListIterator it = new TextFile(args[0]).listIterator();

while(it.hasNext()) {

Matcher m = p.matcher((String)it.next());

while(m.find())

System.out.println(it.nextIndex() + ": " +

m.group() + ": " + m.start());

}

}

} ///:~

文件是用TextFile打开的(本章的前半部分讲的)。由于TextFile会把文件的各行放在ArrayList里面,而我们又提取了一个ListIterator,因此我们可以在文件的各行当中自由移动(既能向前也可以向后)。

每行都会有一个Matcher,然后用find( )扫描。注意,我们用ListIterator.nextIndex( )跟踪行号。

测试参数是JGrep.java和以[Ssct]开头的单词。

还需要StringTokenizer吗?

看到正则表达式能提供这么强大的功能,你可能会怀疑,是不是还需要原先的StringTokenizer。JDK 1.4以前,要想分割字符串,只有用StringTokenizer。但现在,有了正则表达式之后,它就能做得更干净利索了。

//: c12:ReplacingStringTokenizer.java

import java.util.regex.*;

import com.bruceeckel.simpletest.*;

import java.util.*;

public class ReplacingStringTokenizer {

private static Test monitor = new Test();

public static void main(String[] args) {

String input = "But I'm not dead yet! I feel happy!";

StringTokenizer stoke = new StringTokenizer(input);

while(stoke.hasMoreElements())

System.out.println(stoke.nextToken());

System.out.println(Arrays.asList(input.split(" ")));

monitor.expect(new String[] {

"But",

"I'm",

"not",

"dead",

"yet!",

"I",

"feel",

"happy!",

"[But, I'm, not, dead, yet!, I, feel, happy!]"

});

}

} ///:~

有了正则表达式,你就能用更复杂的模式将字符串分割开来——要是交给StringTokenizer的话,事情会麻烦得多。我可以很有把握地说,正则表达式可以取代StringTokenizer。

要想进一步学习正则表达式,建议你看Mastering Regular Expression, 2nd Edition,作者Jeffrey E. F. Friedl (O’Reilly, 2002)。

总结

Java的I/O流类库应该能满足你的基本需求:你可以用它来读写控制台,文件,内存,甚至是Internet。你还可以利用继承来创建新的输入和输出类型。你甚至可以利用Java会自动调用对象的toString( )方法的特点(Java仅有的"自动类型转换"),通过重新定义这个方法,来对要传给流的对象做一个简单的扩展。

但是Java的I/O流类库及其文档还是留下了一些缺憾。比方说你打开一个文件往里面写东西,但是这个文件已经有了,这么做会把原先的内容给覆盖了。这时要是能有一个异常就好了——有些编程语言能让你规定只能往新建的文件里输出。看来Java是要你用File对象来判断文件是否存在,因为如果你用FileOutputStream或FileWriter的话,文件就会被覆盖了。

我对I/O流类库的评价是比较矛盾的;它确实能干很多事情,而且做到了跨平台。但是如果你不懂decorator模式,就会觉得这种设计太难理解了,所以无论是对老师还是学生,都得多花精力。此外这个类库也不完整,否则我也用不着去写TextFile了。此外它没有提供格式化输出的功能,而其他语言都已经提供了这种功能。

但是,一旦你真正理解了decorator模式,并且能开始灵活运用这个类库的时候,你就能感受到这种设计的好处了。这时多写几行代码就算不了什么了。

如果你觉得不解渴(本章只是做个介绍,没想要面面俱到),可以去看Elliotte Rusty Harold 写的Java I/O(O’Reilly, 1999)。这本书讲得更深。

正则表达式

本文分十四个类别对正则表达式的意义进行了解释,这十四各类别是:字符/字符类/预定义字符类/POSIX字符类/https://www.360docs.net/doc/0e2884490.html,ng.Character类/Unicode块和类别的类/边界匹配器/Greedy数量词/Reluctant数量词/Possessive数量词/Logical运算符/Back引用/引用/特殊构造。 1.1.字符 x 字符 x。例如a表示字符a \\ 反斜线字符。在书写时要写为\\\\。(注意:因为java在第一次解析时把\\\\解析成正则表达式\\,在第二次解析时再解析为\,所以凡是不是1.1列举到的转义字符,包括1.1的\\,而又带有\的都要写两次) \0n 带有八进制值 0的字符 n (0 <= n <= 7) \0nn 带有八进制值 0的字符 nn (0 <= n <= 7) \0mnn 带有八进制值 0的字符 mnn(0 <= m <= 3、0 <= n <= 7) \xhh 带有十六进制值 0x的字符 hh \uhhhh 带有十六进制值 0x的字符 hhhh \t 制表符 ('\u0009') \n 新行(换行)符 ('\u000A') \r 回车符 ('\u000D') \f 换页符 ('\u000C') \a 报警 (bell) 符 ('\u0007') \e 转义符 ('\u001B') \cx 对应于 x 的控制符 1.2.字符类 [abc] a、b或 c(简单类)。例如[egd]表示包含有字符e、g或d。 [^abc] 任何字符,除了 a、b或 c(否定)。例如[^egd]表示不包含字符e、g或d。 [a-zA-Z] a到 z或 A到 Z,两头的字母包括在内(范围) [a-d[m-p]] a到 d或 m到 p:[a-dm-p](并集) [a-z&&[def]] d、e或 f(交集) [a-z&&[^bc]] a到 z,除了 b和 c:[ad-z](减去) [a-z&&[^m-p]] a到 z,而非 m到 p:[a-lq-z](减去) 1.3.预定义字符类(注意反斜杠要写两次,例如\d写为\\d) . 任何字符(与行结束符可能匹配也可能不匹配) \d 数字:[0-9] \D 非数字: [^0-9] \s 空白字符:[ \t\n\x0B\f\r] \S 非空白字符:[^\s] \w 单词字符:[a-zA-Z_0-9] \W 非单词字符:[^\w] 1.4.POSIX 字符类(仅 US-ASCII)(注意反斜杠要写两次,例如\p{Lower}写为\\p{Lower})

JAVA正则表达式 Pattern和Matcher

java.util.regex是一个用正则表达式所订制的模式来对字符串进行匹配工作的类库包。 1.简介: java.util.regex是一个用正则表达式所订制的模式来对字符串进行匹配工作的类库包。 它包括两个类:Pattern和Matcher 。 Pattern:一个Pattern是一个正则表达式经编译后的表现模式。 Matcher:一个Matcher对象是一个状态机器,它依据Pattern对象做为匹配模式对字符串展开匹配检查。 首先一个Pattern实例订制了一个所用语法与PERL的类似的正则表达式经编译后的模式,然后一个Matcher实例在这个给定的Pattern实例的模式控制下进行字符串的匹配工作。 以下我们就分别来看看这两个类: 2.Pattern类: Pattern的方法如下: static Pattern compile(String regex) 将给定的正则表达式编译并赋予给Pattern类 static Pattern compile(String regex, int flags) 同上,但增加flag参数的指定,可选的flag参数包括:CASE INSENSITIVE,MULTILINE,DOTALL,UNICODE CASE, CANON EQ int flags() 返回当前Pattern的匹配flag参数. Matcher matcher(CharSequence input) 生成一个给定命名的Matcher对象 static boolean matches(String regex, CharSequence input) 编译给定的正则表达式并且对输入的字串以该正则表达式为模开展匹配,该方法适合于该正则表达式只会使用一次的情况,也就是只进行一次匹配工作,因为这种情况下并不需要生成一个Matcher实例。 String pattern() 返回该Patter对象所编译的正则表达式。 String[] split(CharSequence input) 将目标字符串按照Pattern里所包含的正则表达式为模进行分割。 String[] split(CharSequence input, int limit) 作用同上,增加参数limit目的在于要指定分割的段数,如将limi设为2,那么目标字符串将根据正则表达式分为割为两段。

java中正则表达式的使用

Java代码 1.Java中在某个字符串中查询某个字符或者某个子字串Java代码

Java代码 3.对字符串的分割 Java代码 如果用正则表达式分割就如上所示,一般我们都会使用下面更简单的方法:Java代码 4.字符串的替换/删除 Java代码 如果要把字符串中的@都给删除,只用要空字符串替换就可以了: Java代码

注:对Pattern类的说明: 1.public final class java.util.regex.Pattern是正则表达式编译后的表达法。 下面的语句将创建一个Pattern对象并赋值给句柄pat:Pattern pat = https://www.360docs.net/doc/0e2884490.html,pile(regEx); 有趣的是,Pattern类是final类,而且它的构造器是private。也许有人告诉你一些设计模式的东西,或者你自己查有关资料。这里的结论是:Pattern类不能被继承,我们不能通过new创建Pattern类的对象。 因此在Pattern类中,提供了2个重载的静态方法,其返回值是Pattern对象(的引用)。如:Java代码 1.public static Pattern compile(String regex) { 2.return new Pattern(regex, 0); 3.} 当然,我们可以声明Pattern类的句柄,如Pattern pat = null; 2.pat.matcher(str)表示以用Pattern去生成一个字符串str的匹配器,它的返回值是一个Matcher类的引用。 我们可以简单的使用如下方法:boolean rs = https://www.360docs.net/doc/0e2884490.html,pile(regEx).matcher(str).find();

java正则表达式验证格式(邮箱电话号码)

Java正则表达式验证格式(邮箱、电话号码) package com.firewolf.utils;import java.util.regex.Matcher;import java.util.regex.Pattern;/** * 使用正则表达式验证输入格式* @author liuxing * */public class RegexValidateUtil { public static void main(String[] args) { System.out.println(checkEmail("14_8@qw.df")); System.out.println(checkMobileNumber("071-3534452")); } /** * 验证邮箱* @param email * @return */ public static boolean checkEmail(String email){ boolean flag = false; try{ String check = "^([a-z0-9A-Z]+[-|_|\\.]?)+[a-z0-9A-Z]@([a-z0-9A-Z]+(-[a-z0 -9A-Z]+)?\\.)+[a-zA-Z]{2,}$"; Pattern regex = https://www.360docs.net/doc/0e2884490.html,pile(check); Matcher matcher = regex.matcher(email); flag = matcher.matches(); }catch(Exception e){ flag = false; } return flag; } /** * 验证手机号码* @param mobiles * @return */ public static boolean checkMobileNumber(String

Java中的正则表达式+--++示例详解

Java中的正则表达式 众所周知,在程序开发中,难免会遇到需要匹配、查找、替换、判断字符串的情况发生,而这些情况有时又比较复杂,如果用纯编码方式解决,往往会浪费程序员的时间及精力。因此,学习及使用正则表达式,便成了解决这一矛盾的主要手段。 大家都知道,正则表达式是一种可以用于模式匹配和替换的规范,一个正则表达式就是由普通的字符(例如字符a到z)以及特殊字符(元字符)组成的文字模式,它用以描述在查找文字主体时待匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。 自从jdk1.4推出java.util.regex包,就为我们提供了很好的JAVA正则表达式应用平台。 因为正则表达式是一个很庞杂的体系,所以我仅例举些入门的概念,更多的请参阅相关书籍及自行摸索。 \\ 反斜杠 \t 间隔 ('\u0009') \n 换行 ('\u000A') \r 回车 ('\u000D') \d 数字等价于[0-9] \D 非数字等价于[^0-9] \s 空白符号 [\t\n\x0B\f\r] \S 非空白符号 [^\t\n\x0B\f\r] \w 单独字符 [a-zA-Z_0-9] \W 非单独字符 [^a-zA-Z_0-9] \f 换页符 \e Escape \b 一个单词的边界 \B 一个非单词的边界 \G 前一个匹配的结束 ^为限制开头 ^java 条件限制为以Java为开头字符 $为限制结尾 java$ 条件限制为以java为结尾字符 .为限制一个任意字符 java.. 条件限制为java后除换行外任意两个字符 加入特定限制条件「[]」 [a-z] 条件限制在小写a to z范围中一个字符 [A-Z] 条件限制在大写A to Z范围中一个字符 [a-zA-Z] 条件限制在小写a to z或大写A to Z范围中一个字符 [0-9] 条件限制在小写0 to 9范围中一个字符

JAVA中正则表达式使用介绍

JAVA中正则表达式使用介绍 一、什么是正则表达式 正则表达式是一种可以用于模式匹配和替换的强有力的工具。我们可以在几乎所有的基于UNIX系统的工具中找到正则表达式的身影,例如,vi编辑器,Perl或PHP脚本语言,以及awk或sed shell程序等。此外,象JavaScript这种客户端的脚本语言也提供了对正则表达式的支持。 正则表达式可以让用户通过使用一系列的特殊字符构建匹配模式,进行信息的验证。 此外,它还能够高效地创建、比较和修改字符串,以及迅速地分析大量文本和数据以搜索、移除和替换文本。 例如: 二、基础知识 1.1开始、结束符号(它们同时也属于定位符) 我们先从简单的开始。假设你要写一个正则表达式规则,你会用到^和$符号,他们分别是行首符、行尾符。 例如:/^\d+[0-9]?\d+$/ 1.2句点符号 假设你在玩英文拼字游戏,想要找出三个字母的单词,而且这些单词必须以“t”字母开头,以“n”字母结束。另外,假设有一本英文字典,你可以用正则表达式搜索它的全部内容。要构造出这个正则表达式,你可以使用一个通配符——句点符号“.”。这样,完整的表达式就是“t.n”,它匹配“tan”、“ten”、“tin”和“ton”,还匹配“t#n”、“tpn”甚至“t n”,还有其他许多无意义的组合。这是因为句点符号匹配所有字符,包括空格、Tab字符甚至换行符: 1.3方括号符号 为了解决句点符号匹配范围过于广泛这一问题,你可以在方括号(“[]”)里面指定看来有意义的字符。此时,只有方括号里面指定的字符才参与匹配。也就是说,正则表达式“t[aeio]n”只匹配“tan”、“Ten”、“tin”和“ton”。但“Toon”不匹配,因为在方括号之内你只能匹配单个字符: 1.4“或”符号

轻松学会JAVA中的正则表达式

正则表达式是JA V A语言中比较困难的内容我从网上找了一篇很不错的文章愿与大家分享共同进步 内容如下: 正则表达式之道 原著:Steve Mansour sman@https://www.360docs.net/doc/0e2884490.html, Revised: June 5, 1999 (copied by jm /at/ https://www.360docs.net/doc/0e2884490.html, from https://www.360docs.net/doc/0e2884490.html,/%7esman/regexp.htm, after the original disappeared! ) 翻译:Neo Lee neo.lee@https://www.360docs.net/doc/0e2884490.html, 2004年10月16日 英文版原文 译者按:原文因为年代久远,文中很多链接早已过期(主要是关于vi、sed等工具的介绍和手册),本译文中已将此类链接删除,如需检查这些链接可以查看上面链接的原文。除此之外基本照原文直译,括号中有“译者按”的部分是译者补充的说明。如有内容方面的问题请直接和Steve Mansor联系,当然,如果你只写中文,也可以和我联系。 目录 什么是正则表达式 范例 简单 中级(神奇的咒语) 困难(不可思议的象形文字) 不同工具中的正则表达式 什么是正则表达式 一个正则表达式,就是用某种模式去匹配一类字符串的一个公式。很多人因为它们看上去比较古怪而且复杂所以不敢去使用——很不幸,这篇文章也不能够改变这一点,不过,经过一点点练习之后我就开始觉得这些复杂的表达式其实写起来还是相当简单的,而且,一旦你弄懂它们,你就能把数小时辛苦而且易错的文本处理工作压缩在几分钟(甚至几秒钟)内完成。正则表达式被各种文本编辑软件、类库(例如Rogue Wave的tools.h++)、脚本工具(像awk/grep/sed)广泛的支持,而且像Microsoft的V isual C++这种交互式IDE也开始支持它了。 我们将在如下的章节中利用一些例子来解释正则表达式的用法,绝大部分的例子是基于vi 中的文本替换命令和grep文件搜索命令来书写的,不过它们都是比较典型的例子,其中的概念可以在sed、awk、perl和其他支持正则表达式的编程语言中使用。你可以看看不同工具中的正则表达式这一节,其中有一些在别的工具中使用正则表达式的例子。还有一个关于vi中文本替换命令(s)的简单说明附在文后供参考。 正则表达式基础

Java常用的正则表达式验证

1public class Regex { 2 3/** 4* 检查 email输入是否正确 5* 正确的书写格式为 username@domain 6* @param value 7* @return 8*/ 9public boolean checkEmail(String value, int length) { 10return value.matches("\\w+([-+.]\\w+)*@\\w+([-.]\\w+)*\\.\\w+([-.]\\w+)*")&&value.l ength()<=length; 11 } 12 13/** 14* 检查电话输入是否正确 15* 正确格式 012-87654321、0123-87654321、0123-7654321 16* @param value 17* @return 18*/ 19public boolean checkTel(String value) { 20return value.matches("\\d{4}-\\d{8}|\\d{4}-\\d{7}|\\d(3)-\\d(8)"); 21 } 22 23/** 24* 检查手机输入是否正确 25* 26* @param value 27* @return 28*/ 29public boolean checkMobile(String value) { 30return value.matches("^[1][3,5]+\\d{9}"); 31 } 32 33/** 34* 检查中文名输入是否正确 35* 36* @param value 37* @return 38*/ 39public boolean checkChineseName(String value, int length) { 40return value.matches("^[\u4e00-\u9fa5]+$")&&value.length()<=length; 41 } 42/**

JAVA正则表达式语法

Java 正则表达式 表达式意义: 1.字符 x 字符 x。例如a表示字符a \\ 反斜线字符。在书写时要写为\\\\。(注意:因为java在第一次解析时,把\\\\解析成正则表达式\\,在第二次解析时再解析为\,所以凡是不是1.1列举到的转义字符,包括1.1的\\,而又带有\的都要写两次) \0n 带有八进制值 0的字符 n (0 <= n <= 7) \0nn 带有八进制值 0的字符 nn (0 <= n <= 7) \0mnn 带有八进制值 0的字符 mnn(0 <= m <= 3、0 <= n <= 7) \xhh 带有十六进制值 0x的字符 hh \uhhhh 带有十六进制值 0x的字符 hhhh \t 制表符 ('\u0009') \n 新行(换行)符 ('\u000A') \r 回车符('\u000D') \f 换页符 ('\u000C') \a 报警 (bell) 符('\u0007') \e 转义符 ('\u001B') \c x 对应于 x 的控制符 2.字符类 [abc] a、b或 c(简单类)。例如[egd]表示包含有字符e、g或d。 [^abc] 任何字符,除了 a、b或 c(否定)。例如[^egd]表示不包含字符e、g或d。 [a-zA-Z] a到 z或 A到 Z,两头的字母包括在内(范围) [a-d[m-p]] a到 d或m到 p:[a-dm-p](并集) [a-z&&[def]] d、e或 f(交集) [a-z&&[^bc]] a到 z,除了 b和 c:[ad-z](减去) [a-z&&[^m-p]] a到 z,而非m到 p:[a-lq-z](减去) 3.预定义字符类(注意反斜杠要写两次,例如\d写为\\d)任何字符 (与行结束符可能匹配也可能不匹配) \d 数字:[0-9] \D 非数字: [^0-9] \s空白字符:[ \t\n\x0B\f\r] \S 非空白字符:[^\s] \w 单词字符:[a-zA-Z_0-9] \W 非单词字符:[^\w] 4.POSIX 字符类(仅 U S-ASCII)(注意反斜杠要写两次,例如\p{Lower}写为\\p{Lower}) \p{Lower} 小写字母字符:[a-z]。 \p{U pper} 大写字母字符:[A-Z] \p{A SCII} 所有 A SCII:[\x00-\x7F] \p{A lpha} 字母字符:[\p{Lower}\p{U pper}] \p{Digit} 十进制数字:[0-9] \p{A lnum} 字母数字字符:[\p{A lpha}\p{Digit}] \p{P unc t} 标点符号:!"#$%&'()*+,-./:;<=>?@[\]^_`{|}~ \p{Graph} 可见字符:[\p{A lnum}\p{Punc t}] \p{P rint} 可打印字符:[\p{Graph}\x20]

java中的正则表达式

Java中使用正则表达式验证本地化数据 数据验证是编写任何用户界面时经常要处理的一项杂务。Java? 语言的正则表达式支持可以使数据验证变得更容易。您可以定义一个正则表达式,用于描述有效数据,然后让Java 运行时检查它是否匹配。但是有些类型的数据在不同地区有不同的格式。而ResourceBundle 类让您可以以一种优雅的方式使用特定于地区的数据。本文展示如何结合这两种技术来解决常见的数据输入问题。 本文讨论将正则表达式与Java ResourceBundle 相结合的一种数据验证技术。Java 语言对正则表达式的支持可以大大简化数据验证。您可以将数据与正则表达式进行比较,如果它们匹配,则知道数据是有效的。另一方面,Java ResourceBundle 包含翻译好的字符串,用于匹配用户机器上的当前语言和国家设置。ResourceBundle 中的字符串通常是出现在应用程序中的文本,但是也可以是特定于某个地区的任何东西。 您将实践一个示例应用程序,该应用程序从ResourceBundles 获得正则表达式,并将它们用于数据验证。通过这种方法,就可以用一块代码来验证很多不同类型的数据。更妙的是,随着更多ResourceBundle 的添加,还可以验证更多类型的数据,并且不用更改这段代码中的任何一行。 本文的示例应用程序是在Eclipse 中用Visual Editor 构建的。Visual Editor 是一种用于构建图形化界面的开放源码工具。为了构建自己的应用程序,您需要在计算机上安装Eclipse 和Visual Editor 包。这个示例应用程序只是举例说明了验证数据的一种技巧,所以这种方法可用于任何Java 应用程序。 示例应用程序 我不想花太多的时间讨论这个示例应用程序的所有细节,我只关注其中的数据验证方面的技巧。这个应用程序验证输入到输入域中的邮政编码。您可能知道,在世界的不同地方,邮政编码千差万别。有的是数字,有的则包含字母。即使同是由数字组成的邮政编码,在不同地方其长度也不尽相同。有的国家以特定的模式排列字母和数字,而另外一些国家则采用更自由的格式。所有这些格式都可以用正则表达式来描述。例如,在美国邮政编码是一个五位数,后面还可能跟有一个破折号加一个四位数。清单1 展示了描述这种格式的正则表达式: 清单 1. 用于美国邮政编码的正则表达式

JAVA 正则表达式4种常用的功能

JAVA 正则表达式4种常用的功能下面简单的说下它的4种常用功能: 查询: 以下是代码片段: String str="abc efg ABC"; String regEx="a|f"; //表示a或f Pattern p=https://www.360docs.net/doc/0e2884490.html,pile(regEx); Matcher m=p.matcher(str); boolean rs=m.find(); 如果str中有regEx,那么rs为true,否则为flase。如果想在查找时忽略大小写,则可以写成Pattern p=https://www.360docs.net/doc/0e2884490.html,pile(regEx,Pattern.CASE_INSENSITIVE); 提取: 以下是代码片段: String regEx=".+\(.+)$"; String str="c:\dir1\dir2\name.txt"; Pattern p=https://www.360docs.net/doc/0e2884490.html,pile(regEx); Matcher m=p.matcher(str); boolean rs=m.find(); for(int i=1;i<=m.groupCount();i++){ System.out.println(m.group(i)); } 以上的执行结果为name.txt,提取的字符串储存在m.group(i)中,其中i最大值为

m.groupCount(); 分割: 以下是代码片段: String regEx="::"; Pattern p=https://www.360docs.net/doc/0e2884490.html,pile(regEx); String[] r=p.split("xd::abc::cde"); 执行后,r就是{"xd","abc","cde"},其实分割时还有跟简单的方法:String str="xd::abc::cde"; String[] r=str.split("::"); 替换(删除): 以下是代码片段: String regEx="a+"; //表示一个或多个a Pattern p=https://www.360docs.net/doc/0e2884490.html,pile(regEx); Matcher m=p.matcher("aaabbced a ccdeaa"); String s=m.replaceAll("A"); 结果为"Abbced A ccdeA" 如果写成空串,既可达到删除的功能,比如: String s=m.replaceAll(""); 结果为"bbced ccde" 附: \D 等於[^0-9] 非数字 \s 等於[ \t\n\x0B\f ] 空白字元 \S 等於[^ \t\n\x0B\f ] 非空白字元 \w 等於[a-zA-Z_0-9] 数字或是英文字 \W 等於[^a-zA-Z_0-9] 非数字与英文字

java正则表达式分析

Java 正则表达式 正则表达式定义了字符串的模式。 正则表达式可以用来搜索、编辑或处理文本。 正则表达式并不仅限于某一种语言,但是在每种语言中有细微的差别。 Java 正则表达式和Perl 的是最为相似的。 java.util.regex 包主要包括以下三个类: ?Pattern 类: pattern 对象是一个正则表达式的编译表示。Pattern 类没有公共构造方法。要创建一个Pattern 对象,你必须首先调用其公共静态编译方法,它返回一个Pattern 对象。该方法接受一个正则表达式作为它的第一个参数。 ? ?Matcher 类: Matcher 对象是对输入字符串进行解释和匹配操作的引擎。与Pattern 类一样,Matcher 也没有公共构造方法。你需要调用Pattern 对象的matcher 方法来获得一个Matcher 对象。 ? ?PatternSyntaxException: PatternSyntaxException 是一个非强制异常类,它表示一个正则表达式模式中的语法错误。 ? 捕获组 捕获组是把多个字符当一个单独单元进行处理的方法,它通过对括号内的字符分组来创建。 例如,正则表达式(dog) 创建了单一分组,组里包含"d","o",和"g"。 捕获组是通过从左至右计算其开括号来编号。例如,在表达式((A)(B(C))),有四个这样的组: ?((A)(B(C))) ?(A) ?(B(C))

?(C) 可以通过调用matcher 对象的groupCount 方法来查看表达式有多少个分组。groupCount 方法返回一个int 值,表示matcher对象当前有多个捕获组。 还有一个特殊的组(group(0)),它总是代表整个表达式。该组不包括在groupCount 的返回值中。 实例 下面的例子说明如何从一个给定的字符串中找到数字串: RegexMatches.java 文件代码: 以上实例编译运行结果如下: 正则表达式语法

Java中正则表达式的一个简单例子

Java中正则表达式的一个简单例子 本文由广州疯狂软件java培训分享: import ; public class regexTest { // 新建类 public static void main(String[] args){ // 主方法 Scanner sc = new Scanner(System.in); // new Scanner类对象 "Please Enter Email:"); String email = sc.nextLine(); "Please Enter Mobile:"); String mobile = sc.nextLine(); String Email_regex= "\\w+@\\w+\\.\\w{2,3}"; String Mobile_regex= "^((13[0-9])|(15[0-9])|(18[0-9]))\\d{8}";//设定手机号码正则表达式规则13*,15*,18* if(email.matches(Email_regex)){ + "是个合法的Email Address!"); } else{ + "是个非法的Email Address!"); } if(mobile.matches(Mobile_regex)){ + "是个合法的手机号码"); } else{ + "是个非法的手机号码"); } } } 在程序开发中,难免会遇到需要匹配、查找、替换、判断字符串的情况发生,而这些情况有时又比较复杂,如果用纯编码方式解决,往往会浪费程序员的时间及精力。因此,学习及使用正则表达式,便成了解决这一矛盾的主要手段。大家都知道,正则表达式是一种可以用于模式匹配和替换的规范,一个正则表达式就是由普通的字符(例如字符a到z)以及特殊字符(元字符)组成的文字模式,它用以描述在查找文字主体时待匹配的一个或多个字符串。正则表达式作为一个模板,将某个字符模式与所搜索的字符串进行匹配。 自从jdk1.4推出,就为我们提供了很好的JA V A正则表达式应用平台。 常见的正则表达式规则 匹配特定数字: ^[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*$//匹配正浮点数

JAVA正则表达式语法

JA V A正则表达式语法 正则表达式是一种文本模式,包括普通字符(例如,a 到 z 之间的字母)和特殊字符(称为“元字符”)。模式描述在搜索文本时要匹配的一个或多个字符串。 正则表达式示例 表达式匹配 /^\s*$/ 匹配空行。 /\d{2}-\d{5}/ 验证由两位数字、一个连字符再加 5 位数字组成的 ID 号。 /<\s*(\S+)(\s[^>]*)?>[\s\S]*<\s*\/\1\s*>/ 匹配 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”在内的任意字符,请使用诸如“[\s\S]”之类的模式。 (pattern) 匹配 pattern 并捕获该匹配的子表达式。可以使用$0…$9 属性从结果“匹配”集合中检索捕获的匹配。若要匹配括号字符 ( ),请使用“\(”或者“\)”。 (?:pattern)

java正则表达式判断数字

java正则表达式判断数字 "^\\d+$" //非负整数(正整数+ 0) "^[0-9]*[1-9][0-9]*$" //正整数 "^((-\\d+)|(0+))$" //非正整数(负整数+ 0)"^-[0-9]*[1-9][0-9]*$" //负整数 "^-?\\d+$" //整数 "^\\d+(\\.\\d+)?$" //非负浮点数(正浮点数+ 0) "^(([0-9]+\\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\\.[0-9]+)|([0-9] *[1-9][0-9]*))$" //正浮点数 "^((-\\d+(\\.\\d+)?)|(0+(\\.0+)?))$" //非正浮点数(负浮点数+ 0)

"^(-(([0-9]+\\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\\.[0-9]+)|([0-9]*[1-9][0-9]*)))$" //负浮点数 "^(-?\\d+)(\\.\\d+)?$" //浮点数 2)var r = /^\+?[1-9][0-9]*$/; //正整数 r.test(str); /** * 判断mac地址是否合法, * 要求连接符必须为冒号 * * @author jwang * @date 2013.4.19 * @param macAddress

* @return */ private static boolean isMacAddress(String macAddress){ String reg = "^([0-9a-fA-F]){2}([:][0-9a-fA-F]{2}){5}"; return https://www.360docs.net/doc/0e2884490.html,pile(reg).matcher(macAddress).find(); }

java中的日期验证正则表达式

@Test public void Testregexp(){ //Pattern p = https://www.360docs.net/doc/0e2884490.html,pile("^((\\d{2}(([02468][048])|([13579][26]))[\\/\\/\\s]?((((0?"+"[13578])|( 1[02]))[\\/\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))" +"|(((0?[469])|(11))[\\/\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|" +"(0?2[\\/\\/\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][12"+"35679])|([13579][0 1345789]))[\\/\\/\\s]?((((0?[13578])|(1[02]))" +"[\\/\\/\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))" +"[\\/\\/\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\/\\/\\s]?((0?[" +"1-9])|(1[0-9])|(2[0-8]))))))"); Pattern p = https://www.360docs.net/doc/0e2884490.html,pile("^((\\d{2}(([02468][048])|([13579][26]))[\\-\\-\\s]?((((0?" +"[13578])|(1[02]))[\\-\\-\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))" +"|(((0?[469])|(11))[\\-\\-\\s]?((0?[1-9])|([1-2][0-9])|(30)))|" +"(0?2[\\-\\-\\s]?((0?[1-9])|([1-2][0-9])))))|(\\d{2}(([02468][12" +"35679])|([13579][01345789]))[\\-\\-\\s]?((((0?[13578])|(1[02]))" +"[\\-\\-\\s]?((0?[1-9])|([1-2][0-9])|(3[01])))|(((0?[469])|(11))" +"[\\-\\-\\s]?((0?[1-9])|([1-2][0-9])|(30)))|(0?2[\\-\\-\\s]?((0?[" +"1-9])|(1[0-9])|(2[0-8]))))))"); String s = "2003-02-20"; System.out.println(s + " " + p.matcher(s).matches()); s = "2004/02/29"; System.out.println(s + " " + p.matcher(s).matches()); s = "2004/04/31"; System.out.println(s + " " + p.matcher(s).matches()); s = "2004/04/30"; System.out.println(s + " " + p.matcher(s).matches()); s = "2004/04/30"; System.out.println(s + " " + p.matcher(s).matches()); s = "2004/09/30"; System.out.println(s + " " + p.matcher(s).matches()); } 以上运行结果: 2003-02-20 true 2004/02/29 false 2004/04/31 false 2004/04/30 false

Java正则表达式使用详解(2015版)

Java正则表达式使用详解 2015年4月15日修订 如果你曾经用过Perl或任何其他内建正则表达式支持的语言,你一定知道用正则表达式处理文本和匹配模式是多么简单。如果你不熟悉这个术语,那么“正则表达式”(Regular Expression)就是一个字符构成的串,它定义了一个用来搜索匹配字符串的模式。 许多语言,包括Perl、PHP、Python、JavaScript和JScript,都支持用正则表达式处理文本,一些文本编辑器用正则表达式实现高级“搜索-替换”功能。那么Java又怎样呢?本文写作时,一个包含了用正则表达式进行文本处理的Java规范需求(Specification Request)已经得到认可。 一、正则表达式基础知识 我们先从简单的开始。假设你要搜索一个包含字符“cat”的字符串,搜索用的正则表达式就是“cat”。如果搜索对大小写不敏感,单词“catalog”、“Catherine”、“sophisticated”都可以匹配。也就是说: 1.1 句点符号 假设你在玩英文拼字游戏,想要找出三个字母的单词,而且这些单词必须以“t”字母开头,以“n”字母结束。另外,假设有一本英文字典,你可以用正则表达式搜索它的全部内容。要构造出这个正则表达式,你可以使用一个通配符——句点符号“.”。这样,完整的表达式就是“t.n”,它匹配“tan”、“ten”、“tin”和“ton”,还匹配“t#n”、“tpn”甚至“t n”,还有其他许多无意义的组合。这是因为句点符号匹配所有字符,包括空格、Tab字符甚至换行符: 1.2 方括号符号 为了解决句点符号匹配范围过于广泛这一问题,你可以在方括号(“[]”)里面指定看来有意义的字符。此时,只有方括号里面指定的字符才参与匹配。也就是说,正则表达式“t[aeio]n”只匹配“tan”、“Ten”、“tin”和“ton”。但“Toon”不匹配,因为在方括号之内你只能匹配单个字符: 1.3 “或”符号 如果除了上面匹配的所有单词之外,你还想要匹配“toon”,那么,你可以使用“|”操作符。“|”操作符的基本意义就是“或”运算。要匹配“toon”,使用“t(a|e|i|o|oo)n”正则表达式。这里不能使用方扩号,因为方括号只允许匹配单个字符;这里必须使用圆括号“()”。圆括号还可以用来分组,具体请参见后面介绍。 1.4 表示匹配次数的符号 表一显示了表示匹配次数的符号,这些符号用来确定紧靠该符号左边的符号出现的次数:

java中的日期验证正则表达式

public static void main(String[] args) { String checkValue = "20000431112230"; String year = checkValue.substring(0, 4); // 获取年份 String month = checkValue.substring(4, 6); // 获取月份 Boolean isLeap = leapYear(Integer.parseInt(year)); // 判断闰年 System.out.println(isLeap); StringBuffer eL= new StringBuffer(); String longMonth = "01030507081012"; // 31天的月份 String fix = "([2][0-3]|[0-1][0-9]|[1-9])[0-5][0-9]([0-5][0-9]|[6][0])"; if(isLeap && month.equals("02")){ // 针对2月份的情况【闰年】eL.append("\\d{4}([1][0-2]|[0][0-9])([2][0-1]|[1-2][0-9] |[0][1-9]|[1-9])"+fix); }else if(!isLeap && month.equals("02")){ // 针对2月份的情况【非闰年】 eL.append("\\d{4}([1][0-2]|[0][0-9])([2][0-1]|[1-2][0-8] |[0][1-9]|[1-9])"+fix); }else if(longMonth.contains(month)){ // 31天月份 eL.append("\\d{4}([1][0-2]|[0][0-9])([3][0-1]|[1-2][0-9] |[0][1-9]|[1-9])"+fix); }else{ // 30天月份 eL.append("\\d{4}([1][0-2]|[0][0-9])([3][0]|[1-2][0-9]|[ 0][1-9]|[1-9])"+fix); } Pattern p = https://www.360docs.net/doc/0e2884490.html,pile(eL.toString()); Matcher m = p.matcher(checkValue); boolean flag = m.matches(); if(flag ) { System.out.println("格式正确"); } else { System.out.println("格式错误"); } } public static boolean leapYear(int year) { Boolean isLeap = false; if(((year % 100== 0) && (year % 400== 0)) || ((year % 100!= 0) && (year % 4== 0)))

相关文档
最新文档