`
dingjun1
  • 浏览: 213351 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

JAVA正则表达式

阅读更多
正则表达式
常用语法
正则表达式的构造字符 匹配
X 字符X
\\ 反斜线字符
\0n 带有八进制值0的字符n(0<=n<=7)
\0nn 带有八进制值0的字符nn n(0<=n<=7)
\0mnn 带有八进制值0的字符mnn(0<=m<=3、0<=n<=7)
\xhh 带有十六进制值0Xr的字符hh
\uhhhh 带有十六进制值0x的字符hhhh
\t 制表符(‘\u0009’)
\n 换行符(‘\u0000A’)
\r 回车符(‘\u000D’)

[abc] a 、 b或c
[^abc] 任何字符,除了a、或c
[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](减去)

点:“.” 点:任何字符(与行结束符可能匹配也可能不匹配)
\d 数字:[0-9]
\D 非数字[^0-9]
\s 空白字符[\t\n\x0B\f\t]
\S 非空白字符:[^\s]
\w 单词字符[a-zA-Z_0-9]
\W 非单词字符[^\w]

^ 行的开头
$ 行的结尾
\b 单词边界
\B 非单词边界
\G 上一个匹配的结尾
Greedy 尽可能多的匹配
X? X,一次或一次也没有
X* X,零次或多次
X+ X,一次或多次
X{n} X,恰好 n 次
X{n,} X,至少 n 次
X{n,m} X,至少 n 次,但是不超过 m 次
Reluctant 尽可能少的匹配
X?? X,一次或一次也没有
X*? X,零次或多次
X+? X,一次或多次
X{n}? X,恰好 n 次
X{n,}? X,至少 n 次
X{n,m}? X,至少 n 次,但是不超过 m 次
Possessive
X?+ X,一次或一次也没有
X*+ X,零次或多次
X++ X,一次或多次
X{n}+ X,恰好 n 次
X{n,}+ X,至少 n 次
X{n,m}+ X,至少 n 次,但是不超过 m 次

XY X 后跟 Y
X|Y X 或 Y
(X) X,作为捕获组

\n 任何匹配的 nth 捕获组

(?:X) X,作为非捕获组
捕获组可以通过从左到右计算其开括号来编号 例如,在表达式 ((A)(B(C))) 中,存在四个这样的组
1    ((A)(B(C)))
2    (A)
3    (B(C))
4    (C)
0   组零始终代表整个表达式,与括号无关
?    以 (?) 开头的组是纯的非捕获 组,它不捕获文本,也不针对组合计进行计数。

Java与perl
JAVA支持,但是perl不支持的。这个有很多的方面,现在只说一点:
Possessive quantifiers, which greedily match as much as they can and do not back off, even when doing so would allow the overall match to succeed
Possessive 数量词,它可以尽可能多地进行匹配并且不会回退,即使这样做导致所有匹配都成功时也如此

区分greedy 、reluctant、possessive
Greedy:匹配器尽可能多的接收输入的字符,当第一匹配尝试失败后,匹配器就会在接收到的输入字符串中后退一个字符再次尝试,直到成功或没有符合的字符
Reluctant 匹配器从接收到的第一个字符开始,逐步地一次读一个字符搜索匹配。
Possessive匹配器尽可能多的接收输入的字符,尝试一次匹配,如果失败就失败,不会像Greedy一样后退。
reluctant
import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.regex.PatternSyntaxException;
public class TestRegex2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String str="taaadaadcaaddf";
		/*
“[adc]*”尽可能的接收字符,从第二个字符开始接受,直到倒数第二个字符结束,
“[adc]*”捕获了:“aaadaadcaadd”

接着后面应该连接一个d,但是字符最后一个为f,这时就后退一个字符,再进行匹配,这时括号中(表示一个捕获组,从左到右,在这里表示第一个捕获组)接受了从第二个字符到倒数第三个字符,
“[adc]*”捕获了:“aaadaadcaad”
后退的倒数第二个字符刚好为d,这时匹配成功。

*/

		Pattern p = Pattern.compile("([adc]*)d");
		Matcher m = p.matcher(str);
		print(m,"greedy");
		

/*
“[adc]*?”尽可能少的接收输入字符,首先是接收一个空字符,由于第一个字符为t,不是d,匹配不成功,接着一个字符,这时接受的为第二个字符a,试着匹配,由于第三个字符a,非d,接着接收两个字符,直到接收三个字符后匹配成功。如果需要的话从新的位置开始准备下一轮的匹配,

第后一次匹配成功为一个字符d,“[adc]*?”捕获的为一个空字符。
*/
		Pattern p2 = Pattern.compile("([adc]*?)d");
		Matcher m2 = p2.matcher(str);
		print(m2,"reluctant");
		



/*
“[adc]*+”尽可能的接收字符,从第二个字符开始接受,直到倒数第二个字符结束,
“[adc]*+”捕获了:“aaadaadcaadd”,由于后面应该连接一个d,但是实际输入的为f,匹配失败,且不后退。最后没有匹配成功。
*/
		Pattern p3 = Pattern.compile("([adc]*+)d");
		Matcher m3 = p3.matcher(str);
		print(m3,"possessive3");
		
/*
“[adc]*+”尽可能的接收字符,从第二个字符开始接受,直到倒数第二个字符结束,
“[adc]*+”捕获了:“aaadaadcaadd”,由于后面应该连接一个f,实际输入的为f,匹配成功。
*/

		Pattern p4 = Pattern.compile("([adc]*+)f");
		Matcher m4 = p4.matcher(str);
		print(m4,"possessive4");
	}
	
	public static void print(Matcher m,String style){
		System.out.println("\n"+style);
		while(m.find()){
			if(m.groupCount()>=1)
				System.out.println("第一组捕获组为:"+m.group(1));
			
			System.out.println(m.group()+" start:"+m.start()+" end:"+m.end());
			
			
		}
	}

}



输出结果:

greedy
第一组捕获组为:aaadaadcaad
aaadaadcaadd start:1 end:13

reluctant
第一组捕获组为:aaa
aaad start:1 end:5
第一组捕获组为:aa
aad start:5 end:8
第一组捕获组为:caa
caad start:8 end:12
第一组捕获组为:
d start:12 end:13

possessive3

possessive4
第一组捕获组为:aaadaadcaadd
aaadaadcaaddf start:1 end:14






import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.util.regex.PatternSyntaxException;
public class TestRegular {

	/**
	 * @param args
	 */
	
	
	public static String myStr = "" +
    "<div id=\"head_link\" class=\"padding_nav\">" +
    "<div class=\"toplinkbotton\"><a href=\"../tzgl/dealTzgl.do?action=view\" target=\"_blank\">通知信息</a></div>" +
    "<div class=\"toplinkbotton\"><a href=\"../xxfb/dealXxfb.do?action=lmxxIndex&amp;lmbh=gsxw\" target=\"_blank\">公司新闻</a></div>" +
    "<div class=\"toplinkbotton\"><a href=\"../tpxw/dealTpxw.do?action=tpxwIndex&amp;curpage=1\" target=\"_blank\">图片新闻</a></div>" +
    "</div>";
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		String myRegular = "\\<\\s*a[^\\>]*\\s+href\\s*=\\s*([\"|'])([^\\>]*?)\\1[^\\>]*\\>([^\\</]+)\\</a[^\\>]*\\>";
		Pattern p = Pattern.compile(myRegular,Pattern.CASE_INSENSITIVE);
		Matcher m = p.matcher(myStr);
		
		while(m.find()){
			if(m.groupCount()>=2)
				System.out.println("link:"+m.group(2));
			if(m.groupCount()>=3)
				System.out.println("text:"+m.group(3));
		}
	}

}





忽略大小写

  (?i)abc 表示abc都忽略大小写
  a(?i)bc 表示bc忽略大小写
  a((?i)b)c 表示只有b忽略大小写
也可以用Pattern.compile(rexp,Pattern.CASE_INSENSITIVE)表示整体都忽略大小写

后向引用(back referencing)
在规则表达式中引用以前已经匹配的模式。
String regex = "<h(4|3)>.*?</h(4|3)>";
		String str = "<h3><h4>my.domin/index.jsp</h4><h4>href=\"my.domin/index.jsp</h4></h3>";
		Pattern p = Pattern.compile(regex);
		Matcher m = p.matcher(str);
		while(m.find()){
			System.out.println(m.group());
		}

输出结果为:
<h3><h4>my.domin/index.jsp</h4>
<h4>href="my.domin/index.jsp</h4>
我们可能并不想匹配上:<h3><h4>my.domin/index.jsp</h4>这种情况。这时可以用back referencing,
使用”\1,\2......\9”引用前面匹配上的子模式。
String regex = "<(h4|h3)>.*?</\\1>";
		String str = "<h3><h4>my.domin/index.jsp</h4><h4>my.domin/index.jsp</h4></h3>";
		Pattern p = Pattern.compile(regex);
		Matcher m = p.matcher(str);
		while(m.find()){
			System.out.println(m.group());
		}

输出结果为:
<h3><h4>my.domin/index.jsp</h4><h4>my.domin/index.jsp</h4></h3>;

替换
String regex = "<(h4)>([^<>]*)</\\1>";
		String str = "<h4>my.domin/index.jsp</h4><h4>my.domin/index.jsp</h4>";
		Pattern p = Pattern.compile(regex);
		Matcher m = p.matcher(str);
		while(m.find()){
			System.out.println(m.group());
		}
		System.out.println("替换:");
		System.out.println(m.replaceAll("<h2>$2</h2>"));

输出结果:
<h4>my.domin/index.jsp</h4>
<h4>my.domin/index.jsp</h4>
替换:
<h2>my.domin/index.jsp</h2><h2>my.domin/index.jsp</h2>

非捕获组
      以 (?) 开头的组是纯的非捕获 组,它不捕获文本,也不针对组合计进行计数。就是说,如果小括号中以?号开头,那么这个分组就不会捕获文本,当然也不会有组的编号,因此也不存在Back 引用。
      在Java中,支持的非捕获组,有如下几种:

正向预查,后向预查
负正向预查 负后向预查

(?=X)     X,通过零宽度的正 lookahead
(?!X)     X,通过零宽度的负 lookahead
(?<=X)     X,通过零宽度的正 lookbehind
(?<!X)     X,通过零宽度的负 lookbehind

这四个非捕获组用于匹配表达式X,但是不包含表达式的文本。
(?=X ) 零宽度正先行断言。仅当子表达式 X 在 此位置的右侧匹配时才继续匹配。例如,\w+(?=\d) 与后跟数字的单词匹配,而不与该数字匹配。此构造不会回溯。
(?!X) 零宽度负先行断言。仅当子表达式 X 不在 此位置的右侧匹配时才继续匹配。例如,例如,\w+(?!\d) 与后不跟数字的单词匹配,而不与该数字匹配。
(?<=X) 零宽度正后发断言。仅当子表达式 X 在 此位置的左侧匹配时才继续匹配。例如,(?<=19)99 与跟在 19 后面的 99 的实例匹配。此构造不会回溯。
(?<!X) 零宽度负后发断言。仅当子表达式 X 不在此位置的左侧匹配时才继续匹配。例如,(?<!19)99 与不跟在 19 后面的 99 的实例匹配
举例:
上面都是理论性的介绍,这里就使用一些例子来说明一下问题:
   1、测试匹配性   (?<!4)56(?=9) 这里的含义就是匹配后面的文本56前面不能是4,后面必须是9组成。因此,可以匹配如下文本 5569  ,与4569不匹配。
  2 、提取字符串   提取 da12bka3434bdca4343bdca234bm   提取包含在字符a和b之间的数字,但是这个a之前的字符不能是c,b后面的字符必须是d才能提取。
        例如这里就只有3434这个数字满足要求。那么我们怎么提取呢?
       首先我们写出提取这个字符串的表达式: (?<!c)a(\d+)bd  这里就只有一个捕获组(\d+)
       JAVA代码片段如下:
	 Pattern p = Pattern.compile("(?<!c)a(\\d+)bd");
	 Matcher m = p.matcher("da12bca3434bdca4343bdca234bm");
	 while(m.find()){
	   System.out.println(m.group(1)); //我们只要捕获组1的数字即可。结果 3434
	   System.out.println(m.group(0)); // 0组是整个表达式,看这里,并没有提炼出(?<!c)的字符 。结果 a3434bd
	 }

    可以看到,非捕获组,最后是不会返回结果的,因为它本身并不捕获文本。


优先级:


      \                             转义符
       (), []                        圆括号和方括号
         *, +, ?, {n}, {n,}, {n,m}     限定符
        ^, $,                         位置和顺序
        一竖(这个编辑器显示不了)                           “或”操作

分享到:
评论

相关推荐

    java正则表达式.zip

    Java正则表达式是Java编程语言中用于处理字符串的强大工具,它基于模式匹配的概念,能够高效地进行文本搜索、替换和解析。在Java中,正则表达式主要通过`java.util.regex`包来实现,提供了Pattern和Matcher两个核心...

    java正则表达式匹配工具

    Java正则表达式匹配工具是IT领域中一种强大的文本处理工具,它利用正则表达式(Regular Expression)的规则来查找、替换或者提取文本中的特定模式。正则表达式是一种特殊的字符序列,能够帮助程序员或者用户高效地...

    java正则表达式验证IP地址

    Java正则表达式验证IP地址 Java正则表达式验证IP地址是指使用Java语言中的正则表达式来验证IP地址是否符合标准。IP地址是指在网络通信中用来标识设备的地址,它是一种逻辑地址,通过它可以找到网络中的设备。在...

    java 正则表达式应用jar包 regex-smart.jar

    Java正则表达式是编程语言Java中的一个强大工具,它用于模式匹配、数据验证和文本检索替换。在Java中,正则表达式是通过java.util.regex包提供的接口和类来实现的。`regex-smart.jar`这个库显然是为了简化开发者在...

    使用Java正则表达式分析处理日志

    本篇将围绕“使用Java正则表达式分析处理日志”这一主题,探讨如何利用Java的正则表达式功能来提取、过滤和操作日志数据。 首先,我们需要理解正则表达式的基本概念。正则表达式(Regular Expression)是一种模式...

    JAVA正则表达式大全

    以下是对这些文档标题所涉及的Java正则表达式知识点的详细解释: 1. **正则表达式之道** 这个主题可能涵盖了正则表达式的基础概念,包括元字符、字符类、量词和分组。元字符如`.`代表任意字符,`^`表示行首,`$`...

    Java正则表达式.ppt

    Java正则表达式是一种强大的文本处理工具,广泛用于验证字符串、查找特定模式和替换文本。在Java中,正则表达式提供了简洁而灵活的方式来处理字符串,使得编程人员能够以更高效的方式实现各种文本操作。 正则表达式...

    Java 正则表达式库

    Java正则表达式库是Java开发中不可或缺的一部分,它为开发者提供了一种强大的文本匹配工具。在Java中,正则表达式(Regular Expression)是一种模式匹配语言,用于处理字符串操作,如查找、替换或提取特定模式的数据...

    Java正则表达式测试工具

    Java正则表达式测试工具是面向开发者和爱好者的一款实用程序,它可以帮助用户验证和调试他们的正则表达式。在Java编程环境中,正则表达式是一个强大的字符串处理工具,广泛用于数据验证、文本搜索和替换等任务。这款...

    使用Java正则表达式实现一个简单的身份证号码验证

    ### 使用Java正则表达式实现一个简单的身份证号码验证 #### 一、背景介绍 身份证号码是中国公民的身份标识,由15位或18位数字组成(早期为15位,后改为18位)。其中,第18位是校验码,可能是数字0~9或者大写字母X。...

    常用java正则表达式

    ### 常用Java正则表达式知识点 #### 一、引言 正则表达式是一种强大的工具,用于处理文本并查找模式。多种编程语言,包括Perl、PHP、Python、JavaScript以及Java等均内置了对正则表达式的支持。本文将详细介绍Java...

    java正则表达式截取demo下载即可运行

    Java正则表达式是Java编程语言中用于处理字符串的强大工具,它允许我们通过模式匹配来查找、替换或分割文本。这个“java正则表达式截取demo”提供了一个可以直接运行的示例,帮助开发者理解如何在Java中使用正则...

    java正则表达式教程html版带目录

    Java正则表达式是Java编程语言中的一个强大工具,它用于模式匹配和字符串处理,尤其在数据验证、文本检索和替换等方面发挥着重要作用。本教程是专为初学者设计的HTML版,旨在帮助读者快速掌握Java正则表达式的概念和...

    java正则表达式使用例子

    Java正则表达式是Java编程语言中用于处理字符串的强大工具,它允许我们通过模式匹配来查找、替换或分割文本。在Android开发中,正则表达式尤其重要,因为它们可以帮助我们验证用户输入、处理文本数据或者进行复杂的...

    Java正则表达式应用总结

    Java正则表达式是编程语言Java中用于处理字符串和文本的强大工具。它允许开发者通过模式匹配来执行复杂的文本分析和操作。在Java中,正则表达式的操作主要涉及两个核心类:`java.util.regex.Matcher`和`java.util....

    Java正则表达式详细讲解

    Java正则表达式是Java编程语言中用于处理字符串的强大工具,它允许程序员通过模式匹配来查找、替换或分割文本。在Java中,正则表达式是通过`java.util.regex`包提供的API来实现的。本讲解将深入探讨Java正则表达式的...

    强大的JAVA正则表达式处理包jakarta-oro

    Java正则表达式是编程语言中的一个重要组成部分,用于文本处理和模式匹配。Jakarta ORO(Oracle Regular Expressions for Java)是Apache软件基金会开发的一个强大的Java正则表达式库,它为开发者提供了更为灵活和...

    Java 正则表达式 图片版

    Java正则表达式 Java 正则表达式 图片版 携带方便,查阅方便!~

Global site tag (gtag.js) - Google Analytics