java分割字符串和正则表达式

时间:2022-05-23 00:17:54

java分割字符串和正则表达式
分离字符串

将字符串依所设定的条件予以分离是很常见的操作,例如指令的分离、文本文件的数据读出等。以后者而言,当在文本文件中存储以下的数据时,在读入文件后,将可以使用String的split()来协助每一行的数据分离。

justin 64/5/26 0939002302 5433343
momor 68/7/23 0939100391 5432343
范例6.8是一个简单的示范,假设fakeFileData的数据就是文件中读入的文字数据。

范例6.8 SplitStringDemo.java

public class SplitStringDemo {

public static void main(String args[]) {

String[] fakeFileData = {

"justin/t64/5/26/t0939002302/t5433343",

"momor/t68/7/23/t0939100391/t5432343" };

for(String data : fakeFileData) {

String[] tokens = data.split("/t");

for(String token : tokens) {

System.out.print(token + "/t| ");

}

System.out.println();

}

}

}

 

执行结果:

 

justin | 64/5/26 | 0939002302 | 5433343 |

momor | 68/7/23 | 0939100391 | 5432343 |

split()依所设定的分隔设定,将字符串分为数个子字符串并以String数组返回,这里简单地介绍了split()方法的使用。有些用过Java的人可能会想到java.util.StringTokenizer,基本上API文件中明确的表示StringTokenizer已经是“遗产类”(Legacy Class)了。存在的原因是为了与旧版Java程序的兼容性,不建议在编写新的Java程序时使用,使用split()来代替会是一个好的方案,而且还可以进一步搭配正则表达式来进行字符串分离。

使用正则表达式(Regular Expression)

如果查询J2SE 1.4之后的String在线API手册说明,会发现有matches()、replaceAll()等方法,所传入的自变量是正则表达式(Regular Expression)的字符串。正则表达式最早是由数学家Stephen Kleene于1956年提出,主要使用在字符字符串的格式比对,后来在信息领域广为应用,现在已经成为ISO(国际标准组织)的标准之一。

Java在J2SE 1.4之后开始支持正则表达式,您可以在API文件的java.util.regex.Pattern类中找到支持的正则表达式相关信息,可以将正则表达式应用于字符串的比对、取代、分离等动作上。以下将介绍几个简单的正则表达式。

对于一些简单的字符比对,例如1~9、A~Z等,您可以使用预先定义的符号来表示。
表6-4列出了几个常用的字符比对符号。

表6-4 字符比对符号

.
符合任一字符

/d
符合0~9任一个数字字符

/D
符合0~9以外的字符

/s
符合/t、/n、/x0B、/f、/r等空格符

/w
符合a~z、A~Z、0~9等字符,也就是数字或是字母都符合

/W
符合a~z、A~Z、0~9等之外的字符,也就是除数字与字母外都符合


举例来说,如果有一字符串abcdebcadxbc,若使用.bc来作比对,符合的子字符串有abc、ebc、xbc 3个;如果使用..cd,则符合的子字符串只有abcd。
范例6.9证实了这个说明。

范例6.9 RegularExpressionDemo.java

public class RegularExpressionDemo {

public static void main(String[] args) {

String text = "abcdebcadxbc";

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

for(String token : tokens) {

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

}

System.out.println();

tokens = text.split("..cd");

for(String token : tokens) {

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

}

System.out.println();

 

}

}

执行结果:

 

d ad

ebcadxbc

使用.bc来作比对,由于符合的子字符串有abc、ebc、xbc 3个,所以split()方法会使用这3个字符串为依据来作字符串分离,返回的自然就是不符合表达式.bc的d与ad。同理如果表达式为..cd,则使用split()返回的就是不符合..cd的ebcadxbc。

也可以使用字符类(Character Class)来比较一组字符范围。
表6-5示范了几个字符类的设定方式。

表6-5 字符类范例

 

[abc]
符合a、b或c

[^abc]
符合a或b或c之外的字符

[a-zA-Z]
符合a~z或者是A~Z的字符

[a-d[m-p]]
a~d或者是m~p,也可以写成[a-dm-p]

[a-z&&[def]]
a~z并且是d或e或f,结果就是d或e或f可以符合

[a-z&&[^bc]]
a~z并且不是b或c

[a-z&&[^m-p]]
a~z并且不是m~p

指定一个字符之外,也可以加上“贪婪量词”(Greedy Quantifiers)来指定字符可能出现的次数。表6-6示范了几个例子。

表6-6 贪婪量词范例

X?
X可出现一次或完全没有

X*
X可出现零次或多次

X+
X可出现一次或多次

X{n}
X可出现n次

X{n,}
X可出现至少n次

X{n, m}
X可出现至少n次,但不超过m次

 


另外,还有Reluctant quantifiers、Possessive quantifiers等的指定,可以自行参考java.util.regex.Pattern类API文件中的说明。

在String类中,matches()方法可以让您验证字符串是否符合指定的正则表达式,这通常用于验证使用者输入的字符串数据是否正确,例如电话号码格式;replaceAll()方法可以将符合正则表达式的子字符串置换为指定的字符串;split()方法可以让您依指定的正则表达式,将符合的子字符串排除,剩下的子字符串分离出来并以字符串数组返回。范例6.9已经示范了split()方法的使用,接下来在范例6.10中示范replaceAll()与matches()方法的运用。

范例6.10 UseRegularExpression.java

import java.io.*;

 

public class UseRegularExpression {

public static void main(String args[])

throws IOException {

BufferedReader reader =

new BufferedReader(

new InputStreamReader(System.in));

 

System.out.println("abcdefgabcabc".replaceAll(".bc", "###"));

 

String phoneEL = "[0-9]{4}-[0-9]{6}";

String urlEL = "<a.+href*=*['/"]?.*?['/"]?.*?>";

String emailEL = "^[_a-z0-9-]+(.[_a-z0-9-]+)*" +

"@[a-z0-9-]+([.][a-z0-9-]+)*$";

 

System.out.print("输入手机号码: ");

String input = reader.readLine();

 

if(input.matches(phoneEL))

System.out.println("格式正确");

else

System.out.println("格式错误");

 

System.out.print("输入href标签: ");

input = reader.readLine();

 

// 验证href标签

if(input.matches(urlEL))

System.out.println("格式正确");

else

System.out.println("格式错误");

 

System.out.print("输入电子邮件: ");

input = reader.readLine();

 

// 验证电子邮件格式

if(input.matches(emailEL))

System.out.println("格式正确");

else

System.out.println("格式错误");

}

}

 

执行结果:

 

###defg######

输入手机号码: 0939-100391

格式正确

输入href标签: <a href="http://caterpillar.onlyfun.net">

格式正确

输入电子邮件: caterpillar.onlyfun@gmail.com

格式正确

 

 Pattern和Matcher

String上可使用正则表达式的操作,实际上是利用了java.util.regex.Pattern与java.util.regex.Matcher的功能。当调用String的matches()方法时,实际上是调用Pattern的静态方法matches(),这个方法会返回boolean值,表示字符串是否符合正则表达式。

如果想要将正则表达式视为一个对象来重复使用,可以使用Pattern的静态方法compile()进行编译。compile()方法会返回一个Pattern的实例,这个实例代表正则表达式,之后就可以重复使用Pattern实例的matcher()方法来返回一个Matcher的实例,代表符合正则式的实例,这个实例上有一些寻找符合正则式条件的方法可供操作。范例6.11作了示范。

范例6.11 UsePatternMatcher.java

import java.util.regex.*;

 

public class UsePatternMatcher {

public static void main(String[] args) {

String phones1 =

"Justin 的手机号码:0939-100391/n" +

"momor 的手机号码:0939-666888/n";

 

Pattern pattern = Pattern.compile(".*0939-//d{6}");

Matcher matcher = pattern.matcher(phones1);

 

while(matcher.find()) {

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

}

 

String phones2 =

"caterpillar 的手机号码:0952-600391/n" +

"bush 的手机号码:0939-550391";

 

matcher = pattern.matcher(phones2);

 

while(matcher.find()) {

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

}

}

}

范例6.11会寻找手机号码为0939开头的号码,假设号码来源不止一个(如phones1、phones2),则可以编译好正则表达式并返回一个Pattern对象,之后就可以重复使用这个Pattern对象,在比对时使用matcher()返回符合条件的Matcher实例。find()方法表示是否有符合的字符串,group()方法则可以将符合的字符串返回。程序的执行结果如下:

 

Justin 的手机号码:0939-100391

momor 的手机号码:0939-666888

bush 的手机号码:0939-550391

 

下面使用Pattern与Matcher改写范例6.9,让程序可以返回符合正则式的字符串,而不是返回不符合的字符串。

范例6.12 RegularExpressionDemo2.java

import java.util.regex.*;

 

public class RegularExpressionDemo2 {

public static void main(String[] args) {

String text = "abcdebcadxbc";

 

Pattern pattern = Pattern.compile(".bc");

Matcher matcher = pattern.matcher(text);

 

while(matcher.find()) {

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

}

System.out.println();

}

}

 

执行结果:

 


abc

ebc

xbc