Java学习系列(二十四)Java正则表达式详解

转载请注明出处:http://blog.csdn.net/lhy_ycu/article/details/45501777

前言

正则表达式可以说是用来处理字符串的一把利器,它是一个专门匹配n个字符串的字符串模板,本质是查找和替换。在实例演示之前先了解一下Pattern、Matcher这两个工具类,Pattern:编译好的带匹配的模板(如:Pattern.compile("[a-z]{2}");/ / 取2个小写字母);Matcher:匹配目标字符串后产生的结果(如:pattern.matcher("目标字符串");)。字符串还有一个自带的matches方法用来判断目标字符串是否匹配给定的正则表达式,格式为:targetStr.matches(regex);
返回类型为boolean。

基本使用方式

(一)支持的基本通配符:

.   -可以匹配任意字符

\s  -代表一个任意空白(空格、Tab)。

\S  -代表一个任意的非空白。

\d  -代表一个任意的数字(digital)。

\D  -代表一个任意的非数字。

\w  -代表一个单词字符。

-W  -代表一个任意的非单词字符

注意:对于特殊字符,实际使用时记住要转义\ ,如:( ) [ ] { } \ ? * + ^(一行的开头) $(一行的结尾)|

(二)取值范围(用作出现次数的“副词”)

? --代表它前面的东西可以出现0~1次

* --代表它前面的东西可以出现0~N次

+ --代表它前面的东西可以出现1~N次

{n,m} --代表它前面的东西可以出现n~m次

{n,} --代表它前面的东西至少出现n次

{,m} --代表它前面的东西最多出现m次

{n} --代表它前面的东西必须出现n次

(三)方括号表达式

枚举:[ab1]  --代表a或b或者1。

范围:[a-c]  --代表a,b,c中的任意一个字符。

枚举与范围:[a-c1-3]--代表a,b,c,1,2,3中的任意一个字符。

表示求否:[^a-c] --代表不含a,b,c其中任意一个字符。

表示求交:[a-g&&[^b-d]]:--代表a,e,f,g中的任意一个字符。

表示必须含有其中之一:(com|org|cn)

总结:一个字符用\,多个字符用[],字符次数用{} 

实例说明

(一)基本用法演示:

/**
 * 正则表达式实例演示说明
 *
 * @author [*昨日重现*] [email protected]
 * @since version 1.0
 * @datetime 2015年5月5日 下午2:27:50
 */

public class RegexTest {

	public static void main(String[] args) {
		// 单个字符
		System.out.println("a".matches("."));
		// 0~1个a
		System.out.println("a".matches("a?"));
		// 1~N个a
		System.out.println("aaaa".matches("a+"));
		// 0~N个a
		System.out.println("".matches("a*"));
		// 1~N个q和1个0~9之间的数字
		System.out.println("qqqqqq3".matches("q+[0-9]"));
		// 12~100个数字
		System.out.println("12345667890123".matches("\\d{12,100}"));
		// 0~3个数字分别以.分割
		System.out.println("192.168.0.1"
				.matches("\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}"));
		// 第一个数字0~2,第二个数字0~9,第三个数字0~9
		System.out.println("192".matches("[0-2][0-9][0-9]"));
		// 4个任意空白
		System.out.println(" \n\r\t".matches("\\s{4}"));
		// 特殊字符\需转义
		System.out.println("\\".matches("\\\\"));
		// 以h开头,中间有0~N个字符,最后以o结尾
		System.out.println("hello".matches("^.*o$"));
		// 以h开头,中间1~3个字母尾随一个o,接着空白连着0~N个字符并以d结尾
		System.out.println("hello world".matches("^h[a-z]{1,3}o\\b.*d$"));
		// 以任意空白且不以换行开头为开头,并以换行结尾
		System.out.println("   \n".matches("^[\\s&&[^\\n]]*\\n$"));
		// 0~N个字符,连接4个数字和一个字符
		System.out.println("aaa 2222q".matches(".*\\d{4}."));
	}

}

(二)实际应用演示:

1、读取网页中所有的邮箱地址

/**
 * 读取某个网页中的所有邮箱地址--基本查找
 *
 * @author [*昨日重现*] [email protected]
 * @since version 1.0
 * @datetime 2015年5月5日 下午4:20:00
 */

public class EmailTest {

	public static void main(String[] args) {
		// 1~N个单词(可能含有.、-)连接 @1~N个单词连着 . 最后以com|org|cn|net其中之一结尾
		String emailTemplate = "[\\w[.-]][email protected][\\w]+\\.(com|org|cn|net)";
		BufferedReader br = null;
		try {
			br = new BufferedReader(new InputStreamReader(new FileInputStream(
					"d:\\email.html")));
			String line = null;
			StringBuffer sb = new StringBuffer();
			while ((line = br.readLine()) != null) {
				sb.append(line).append("\n");
			}
			parse(sb.toString(), emailTemplate);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			try {
				br.close();
			} catch (Exception e2) {
				// TODO: handle exception
				e2.printStackTrace();
			}
		}

	}

	/**
	 * 打印网页中的所有邮箱地址
	 *
	 * @param targetStr
	 *            目标字符串
	 * @param template
	 *            待编译的正则模板
	 */
	public static void parse(String targetStr, String template) {
		if (targetStr == null || template == null) {
			return;
		}
		// 获取编译好的待匹配的模板
		Pattern pattern = Pattern.compile(template);
		// 获取匹配目标字符串后产生的结果
		Matcher matcher = pattern.matcher(targetStr);
		// 若查找下一个匹配正则表达式的字符串
		while (matcher.find()) {
			// 则取出上一次与正则表达式匹配的字串。
			System.out.println("=======" + matcher.group());
		}
	}

}

2、代码行数统计:

/**
 * 代码统计:遍历某个项目的源文件的代码行数。
 *
 * 包括:空白行数、代码行数、注释行数。
 *
 * @author [*昨日重现*] [email protected]
 * @since version 1.0
 * @datetime 2015年5月5日 下午4:40:12
 */

public class CodeCounter {
	/**
	 * 空白行数
	 */
	private static long whiteLines = 0;
	/**
	 * 代码行数
	 */
	private static long normalLines = 0;
	/**
	 * 注释行数
	 */
	private static long commentLines = 0;

	public static void main(String[] args) {
		 File srcDir = new File("D:\\workspace\\android\\Abc\\src");
		myList(srcDir);// 遍历所java源文件
		System.out.println("whiteLines = " + whiteLines);
		System.out.println("normalLines = " + normalLines);
		System.out.println("commentLines = " + commentLines);
		System.out.println("totalLines = " + getTotalLines());
	}

	/**
	 * 获取总行数
	 */
	private static long getTotalLines() {
		long value = whiteLines + normalLines + commentLines;
		return value;
	}

	/**
	 * 遍历所java源文件
	 */
	private static void myList(File srcDir) {
		System.out.println(srcDir + "目录下包含的目录和子文件有:");
		File[] files = srcDir.listFiles();
		for (File file : files) {
			System.out.println("----------" + file);
			if (file.getName().matches(".*\\.java$")) {
				parse(file);
			}
			if (file.isDirectory()) {
				myList(file);
			}
		}
	}

	/**
	 * 读取源文件内容
	 *
	 * @param file
	 *            java文件
	 */
	private static void parse(File file) {
		BufferedReader br = null;
		/**
		 * 标识注释的开始或结束
		 */
		boolean comment = false;
		try {
			br = new BufferedReader(new InputStreamReader(new FileInputStream(
					file)));
			String line = null;
			while ((line = br.readLine()) != null) {
				line = line.trim();
				// 以任意空白且不以换行开头为开头,并以换行结尾
				if (line.matches("^[\\s&&[^\\n]]*$")) {
					whiteLines++;
				} else if (line.startsWith("/*")) {
					commentLines++;
					comment = true;
				} else if (comment == true) {
					commentLines++;
					if (line.endsWith("*/")) {
						comment = false;
					}
				} else if (line.contains("//")) {
					commentLines++;
				} else {
					normalLines++;
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			if (br != null) {
				try {
					br.close();
					br = null;
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
	}
}

(三)正则表达式进阶使用:

查找子串

String s1 = "123-45678-987-11";
		Pattern pattern = Pattern.compile("\\d{3,5}"); // 匹配3~5个数字
		Matcher matcher = pattern.matcher(s1);
		System.out.println(matcher.matches());// false
		matcher.reset();// 重置匹配器,将其添加位置设置为零
		System.out.println(matcher.find());// true,由于重置了匹配器此时将从起始位置查找
		System.out.println(matcher.start() + "-" + matcher.end());// 位置:0-3
		// 与matches方法唯一不同的是lookingAt不需要匹配整个区域 ,它永远是从第一个子串开始
		System.out.println(matcher.lookingAt());// true
		System.out.println(matcher.lookingAt());// true

查找与替换

// CASE_INSENSITIVE:忽略子串大小写
		Pattern pattern2 = Pattern.compile("java", Pattern.CASE_INSENSITIVE);
		Matcher matcher2 = pattern2
				.matcher("java Java JAVA jaVA jAVA ILoveYouJaVA youhateJaVa");
		// 将查找到的所有子串进行替换 (查找并替换)
		System.out.println(matcher2.replaceAll("JAVA"));

结束语

关于Java中正则表达式的基本使用差不多就这些了,当然正则表达式的作用远不止这些,至于更深层次的应用以后遇到了会更新上去。截止目前,JavaSE基础差不多到这里了,后面会更新Java性能优化、深入理解JVM、Android学习系列等,敬请期待!

时间: 2024-08-03 11:28:55

Java学习系列(二十四)Java正则表达式详解的相关文章

Java学习系列(二十二)Java面向对象之枚举详解

转载请注明出处:http://blog.csdn.net/lhy_ycu/article/details/45332565 一.前言 今天我们来讲讲枚举,希望通过这篇博客大家能对枚举有个更全面的了解.枚举是一种实例(大写)数固定的类(不能再创建实例),多用于确定的状态数(如:鼠标上下左右.IM消息已读未读).类型数(如:系统.聊天.添加好友消息,我的他的).模式数(回复.评论模式,刷选.全部模式)等等.枚举和类一样,同样有抽象类.可以实现接口.可含内部类.初始化块,值得注意的是:枚举的构造器无论

Java学习系列(二十)Java面向对象之反射详解

转载请注明出处:http://blog.csdn.net/lhy_ycu/article/details/45289391 前言 今天讲讲Java中的反射.我们常见的反射多用于JDBC中的加载驱动程序Class.forName("com.mysql.jdbc.Driver");.Struts的MVC.Hibernate中的ORM.Spring中的IOC还有一些其他框架等等.那它有什么好处呢?它的好处就是能够动态的创建对象和编译且能够访问某个类中的所有(包括私有)属性方法及对象的属性方法

Cocos2d-x学习笔记(十四)CCAutoreleasePool详解

原创文章,转载请注明出处:http://blog.csdn.net/sfh366958228/article/details/38964637 前言 之前学了那么多的内容,几乎所有的控件都要涉及内存管理类CCAutoreleasePool,所以这一次的学习笔记,我们一起来看看CCAutoreleasePool,先从CCObject的autorelease方法入手. CCObject::autorelease CCObject* CCObject::autorelease(void) { // 将

Android学习笔记二十四之ListView列表视图二

Android学习笔记二十四之ListView列表视图二 前面一篇我们介绍了常用的几种适配器的简单实现和ListView的简单使用,这一篇中,我们介绍一下ListView的优化和一些其它的问题. ListView优化方法一 在ListView中,我们最常用的就是自定义Adapter,在我们自定义Adapter中,需要实现两个比较重要的方法getCount()和getView(),前者是负责计算ListView的总Item数,后者是生成Item,有多少个Item就会调用getView()方法多少次

马哥学习笔记二十四——分布式复制快设备drbd

DRBD: 主从 primary: 可执行读.写操作 secondary: 文件系统不能挂载 DRBD: dual primay, 双主(基于集群文件系统的高可用集群) 磁盘调度器:合并读请求,合并写请求: Procotol:drbd数据同步协议 A: Async, 异步  数据发送到本机tcp/ip协议栈 B:semi sync, 半同步  数据发送到对方tcp/ip协议 C:sync, 同步  数据到达对方存储设备 DRBD Source: DRBD资源 资源名称:可以是除了空白字符外的任意

quick-cocos2d-x 学习系列之十四 测试用例

quick-cocos2d-x 学习系列之十四 测试用例 定义变量,创建13个场景名字 local items = { "framework.helper", "framework.native", "framework.display", "framework.crypto", "framework.network", "framework.luabinding", "fra

angular学习笔记(二十四)-$http(2)-设置http请求头

1. angular默认的请求头: 其中,Accept 和 X-Requested-With是$http自带的默认配置 2. 修改默认请求头: (1) 全局修改(整个模块) 使用$httpProvider依赖 var myApp = angular.module('MyApp',[]); myApp.config(function($httpProvider){ console.log($httpProvider.defaults.headers.common) //修改/操作$httpProv

Android 基础总结:( 十四)Handler详解(上)

Handler的定义: 主要接受子线程发送的数据, 并用此数据配合主线程更新UI. 解释: 当应用程序启动时,Android首先会开启一个主线程 (也就是UI线程) , 主线程为管理界面中的UI控件,进行事件分发,比如说,你要是点击一个 Button ,Android会分发事件到Button上,来响应你的操作. 如果此时需要一个耗时的操作,例如:联网读取数据,或者读取本地较大的一个文件的时候,你不能把这些操作放在主线程中,如果你放在主线程中的话,界面会出现假死现象,如果5秒钟还没有完成的话,会收

Java学习系列(二十一)Java面向对象之注解详解

转载请注明出处:http://blog.csdn.net/lhy_ycu/article/details/45295947 一.前言 Java中的注解Annotation运用到很多方面,比如之前讲的单元测试中的@Test.Spring.SpringMVC还有其他框架等等.Java本身自带的注解也有一些,比如:@Override(子类要重写/覆写父类的对应方法).@Deprecated(表示方法不建议被使用).@SuppressWarnings(抑制警告)等等.当然,我们也可以自定义一些自己需要的