正则表达式

正则表达式

在计算理论或编译原理中曾经论述过用正则文法来做词法分析,所以正则文法具备表达任何字符串的能力。正则表达式的表达能力和正则文法相当,所以任何字符串都可以用正则表达式表达。在实际的编程中,我们通常会遇到字符串匹配、过滤等操作,而这种操作往往可以通过正则表达式来解决,所以正则表达式是一种强大而灵活的文本处理工具。使用正则表达式,我们能够以编程的方式构造复杂的文本模式,并对输入的字符串进行处理。一般常用的语言都会提供相应的语言库API来支持正则表达式,如Javajava.util.regex包下的Matcher类和Pattern类,以及对正则表达式具有全面支持和优化过的Jakarta-ORO库。

正则表达式的语法

首先,我们来看一下正则表达式中字符的种类,在《编译原理》这门课中提到字符可以分成普通字符元字符(metacharacter)两种。正则表达式中的元字符包括:^, $, ?, *, +, (, ), {, }, [, ], \, .,  等等,这些元字符或其组合具有特殊的含义,详见下述。那如何表示这些元字符表示的普通字符呢?比如,我需要一个正则表达式以‘?’开始,应该如何表示呢?是这样吗:^?[.]*;显然不是,正确的表示方法应该为:^\?[.]*,正则表达式采用反斜杠来进行转义反斜杠后面跟元字符可以获得元字符对应的普通字符,如\\, \*, ...;反斜杠后面跟部分普通字符可以获得一些不可表示的字符,如\n, \t, \s, \S...

^:行的开头             $:行的结尾

例:^s.*a$  表示以 开头,以 结尾的字符串

?:重复0次或1          *:重复0次或多次         +:重复1次及1次以上

例:a[cd]? 可以匹配:a, ac, ad  

{n}:重复n     {m , n}:重复m~n       {m,}:重复m次以上 

[ ]        []中包含一系列字符,但只能匹配其中的任意一个,[]中所有特殊字符都将失去其特殊含义

正则表达式[]中,’-’有着特殊的意义,表示一个范围,对于’-’字符,需转义’\-’,在[]外则不需要转义

’[]’中,’^’表示不想匹配的字符

( ):           在被修饰匹配次数的时候,括号中的表达式可以作为整体被修饰

               如:(abc)+  用于匹配abc, abcabc, abcabcabc…

                abc+  用于匹配abc, abcc, abccc…

           取匹配结果的时候,括号中的表达式匹配到的内容可以被单独得到(见示例)

\s: 匹配所有空白字符,包括Tab字符

\S: 匹配所有非空白字符[^\t\n\r\f]

\w: [a-zA-Z0-9]

\d:[0-9]

\D:[^0-9]

综上所述,我们发现正则表达式足以表示任意的字符串,元字符的类型可以分成以下几类:

边界标识:^, $

选择(switch):| , [ ] , [ - ] , [^  ]

重复(while):?, *, +, {m, n}

跟元字符(正则表达式中最重要的元字符):\

表示字符类别的方法有[ ] , \d, \D, \s, \S, \w, \W

还有需要注意的就是在字符类别[ ]内,元字符将失去意义而变成普通字符(^除外,^表示非的意思),还有就是 '-' 在[ ]内表示范围,在[ ]外表示普通字符 

Java正则表达式

对于java中的正则表达式,需要注意的一点是’\’的使用。在其他语言中,\\表示“我想要在正则表达式中插入一个普通的反斜线,请不要给他任何特殊的意义”;在java中,\\的意思是“我想要插入一个正则表达式的反斜线,其后面的字符具有特殊意义”。因此,Java中表示普通字符’\’需要使用”\\\\”’\’java字符串中为转义字符(如回车表示为’\r’,换行表示为’\n’,反斜杠表示为’\\’,制表符表示为’\t’),所以当java读到字符串”\\\\”时,将其解释为’\\’作为正则表达式的输入,而在正则表达式中,’\’同样为转义字符,所以其表示反斜杠需要使用’\\’,因此对于java中的字符串”\\\\”,最终被解释为’\’。而对于正则表达式中的’\w’’\d’’\D’’\s’’\S’等表达式,在java中需写为’\\w’’\\d’’\\D’’\\s’’\\S’.

在Java中使用正则表达式的最简单的方式是使用String类内建的功能mathes、split、replace、replaceAll、replaceFirst;参加下面代码:

import java.util.Arrays;

public class StringRegularExpression {
	private static String num = "+911";
	private static String knights = "Then When you find me I love you";
	
	public static void main(String[] args) {
		System.out.println(num.matches("(-|\\+)?\\d+"));  // 匹配
		
		System.out.println(Arrays.toString(knights.split("n\\s")));   // 分割
		System.out.println(Arrays.toString(knights.split("n\\s", 1)));
		
		System.out.println(knights.replaceFirst("y\\w{1,}u", "me"));  // 替换
		System.out.println(knights.replaceAll("y\\w{1,}u", "me"));
		System.out.println(knights.replace("you", "me"));
	}
}
 运行结果: 

true
[The, Whe, you find me I love you]
[Then When you find me I love you]
Then When me find me I love you
Then When me find me I love me
Then When me find me I love me

在Java中使用正则表达式,一般都会通过Pattern.compile(String regex)构造一个类型为Pattern的正则表达式对象p,然后将字符串传入p的matcher()方法生成一个Matcher对象.

Pattern类提供了一个静态的matches方法: 

         static boolean matches(String regex, CharSequence input)   // 检测regex是否匹配input参数代表的字符串

Pattern类提供了split方法,通过Pattern对象表示的正则表达式断开字符串:

         String[] split(CharSequence input)

         String[] split(CharSequence input , int limit)

Matcher类也提供了很多有用的方法:

         boolean find() , boolean find(int i):find()用于在CharSequence中查找多个匹配,find(i)用于从第i个位置查找匹配(匹配字符串的任意位置

         boolean lookingAt(): 判断字符串的起始部分是否能够匹配正则表达式

         boolean matches(): 判断整个字符串是否能够匹配正则表达式

         String group(), String group(int i): 组使用括号划分的正则表达式,可以根据组的编号引用组; 例如:A(B(C))D, 组0为ABCD,组1为BC,组2为C; group()返回前一次匹配操作的第0组,group(i)返回前一次匹配的第i组;

         int groupCount(): 返回该匹配器模式中的分组数目,第0组不包含在内

         int start() , int end():  start()返回先前匹配的起始位置的索引,end()返回所匹配的最后一个字符的索引加1

 Matcher reset() , Matcher reset(String): reset()将Matcher对象重新置到当前字符序列的其实位置;reset(String str)将Matcher对象用于一个新的字符序列

替换操作:

         String replaceFirst(String replacement): 以参数replacement替换掉成功匹配的第一个部分 

         String replaceAll(String replacement): 以参数replacement替换掉成功匹配的所有部分

         appendReplacement(StringBuffer sbuf, String replacement): 执行渐进式替换

         appendTail(StringBuffer sbuf): 执行一次或多次appendReplacement()之后,将剩余字符串复制到sbuf中

import java.util.Arrays;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


public class RegularExpression {
	private static String str = "Here Block My Love Block Here Yx";
	public static void main(String[] args) {
		System.out.println(Pattern.matches("^H.*e$", str));
		
		Pattern p = Pattern.compile("\\s+");
		System.out.println(Arrays.toString(p.split(str)));
		System.out.println(Arrays.toString(p.split(str, 2)));
		
		Pattern p1 = Pattern.compile("[aeiou]");
		Matcher m = p1.matcher(str);
		System.out.println("m.matches(): " + m.matches());
		System.out.println("m.lookingAt(): " + m.lookingAt());
		System.out.println("m.find(): " + m.find());
		
		m.reset();
		StringBuffer sbuf = new StringBuffer();
		while(m.find()){
			m.appendReplacement(sbuf, m.group().toUpperCase());
		}
		m.appendTail(sbuf);
		System.out.println(sbuf.toString());
		
		System.out.println(m.replaceAll("&"));
	}
}

运行结果为:

false
[Here, Block, My, Love, Block, Here, Yx]
[Here, Block My Love Block Here Yx]
m.matches(): false
m.lookingAt(): false
m.find(): true
HErE BlOck My LOvE BlOck HErE Yx
H&r& Bl&ck My L&v& Bl&ck H&r& Yx

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值