0

0

java 正则表达式

伊谢尔伦

伊谢尔伦

发布时间:2016-12-05 10:36:10

|

1427人浏览过

|

来源于php中文网

原创

java 提供了功能强大的正则表达式api,在java.util.regex 包下。本教程介绍如何使用正则表达式api。

正则表达式

一个正则表达式是一个用于文本搜索的文本模式。换句话说,在文本中搜索出现的模式。例如,你可以用正则表达式搜索网页中的邮箱地址或超链接。

正则表达式示例

下面是一个简单的Java正则表达式的例子,用于在文本中搜索 http://

立即学习Java免费学习笔记(深入)”;

String text    =        
   "This is the text to be searched " +       
  "for occurrences of the http:// pattern.";String pattern = ".*http://.*";boolean matches = Pattern.matches(pattern, text);
System.out.println("matches = " + matches);

示例代码实际上没有检测找到的 http:// 是否是一个合法超链接的一部分,如包含域名和后缀(.com,.net 等等)。代码只是简单的查找字符串 http:// 是否出现。

Java6 中关于正则表达式的API

本教程介绍了Java6 中关于正则表达式的API。

Pattern (java.util.regex.Pattern)

类 java.util.regex.Pattern 简称 Pattern, 是Java正则表达式API中的主要入口,无论何时,需要使用正则表达式,从Pattern 类开始

Pattern.matches()

检查一个正则表达式的模式是否匹配一段文本的最直接方法是调用静态方法Pattern.matches(),示例如下:

String text    =        
  "This is the text to be searched " +        
  "for occurrences of the pattern.";String pattern = ".*is.*";boolean matches = Pattern.matches(pattern, text);
System.out.println("matches = " + matches);

上面代码在变量 text 中查找单词 “is” 是否出现,允许”is” 前后包含 0或多个字符(由 .* 指定)

Pattern.matches() 方法适用于检查 一个模式在一个文本中出现一次的情况,或适用于Pattern类的默认设置。

如果需要匹配多次出现,甚至输出不同的匹配文本,或者只是需要非默认设置。需要通过Pattern.compile() 方法得到一个Pattern 实例。

Pattern.compile()

如果需要匹配一个正则表达式在文本中多次出现,需要通过Pattern.compile() 方法创建一个Pattern对象。示例如下

String text    =        
"This is the text to be searched " +        
"for occurrences of the http:// pattern.";
String patternString = ".*http://.*";
Pattern pattern = Pattern.compile(patternString);

可以在Compile 方法中,指定一个特殊标志:

Pattern pattern = Pattern.compile(patternString, Pattern.CASE_INSENSITIVE);

Pattern 类包含多个标志(int 类型),这些标志可以控制Pattern 匹配模式的方式。上面代码中的标志使模式匹配是忽略大小写

Pattern.matcher()

一旦获得了Pattern对象,接着可以获得Matcher对象。Matcher 示例用于匹配文本中的模式.示例如下

Matcher matcher = pattern.matcher(text);

Matcher类有一个matches()方法,可以检查文本是否匹配模式。以下是关于Matcher的一个完整例子

String text    =        
"This is the text to be searched " +        
"for occurrences of the http:// pattern.";
String patternString = ".*http://.*";
Pattern pattern = Pattern.compile(patternString, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(text);boolean matches = matcher.matches();
System.out.println("matches = " + matches);

Pattern.split()

Pattern 类的 split()方法,可以用正则表达式作为分隔符,把文本分割为String类型的数组。示例:

String text = "A sep Text sep With sep Many sep Separators";String patternString = "sep";
Pattern pattern = Pattern.compile(patternString);String[] split = pattern.split(text);
System.out.println("split.length = " + split.length);for(String element : split){
    System.out.println("element = " + element);
}

上例中把text 文本分割为一个包含5个字符串的数组。

Pattern.pattern()

Pattern 类的 pattern 返回用于创建Pattern 对象的正则表达式,示例:

String patternString = "sep";Pattern pattern = Pattern.compile(patternString);String pattern2 = pattern.pattern();

上面代码中 pattern2 值为sep ,与patternString 变量相同。

Matcher (java.util.regex.Matcher)

java.util.regex.Matcher 类用于匹配一段文本中多次出现一个正则表达式,Matcher 也适用于多文本中匹配同一个正则表达式。

Matcher 有很多有用的方法,详细请参考官方JavaDoc。这里只介绍核心方法。

以下代码演示如何使用Matcher

String text    =        
"This is the text to be searched " +        
"for occurrences of the http:// pattern.";
String patternString = ".*http://.*";
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher(text);
boolean matches = matcher.matches();

首先创建一个Pattern,然后得到Matcher ,调用matches() 方法,返回true 表示模式匹配,返回false表示不匹配。

可以用Matcher 做更多的事。

创建Matcher

通过Pattern 的matcher() 方法创建一个Matcher。

String text    =        
"This is the text to be searched " +        
"for occurrences of the http:// pattern.";
String patternString = ".*http://.*";
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher(text);

matches()

Matcher 类的 matches() 方法用于在文本中匹配正则表达式

boolean matches = matcher.matches();

如果文本匹配正则表达式,matches() 方法返回true。否则返回false。

matches() 方法不能用于查找正则表达式多次出现。如果需要,请使用find(), start() 和 end() 方法。

lookingAt()

lookingAt() 与matches() 方法类似,最大的不同是,lookingAt()方法对文本的开头匹配正则表达式;而

matches() 对整个文本匹配正则表达式。换句话说,如果正则表达式匹配文本开头而不匹配整个文本,lookingAt() 返回true,而matches() 返回false。 示例:

String text    =        
"This is the text to be searched " +        
"for occurrences of the http:// pattern.";
String patternString = "This is the";
Pattern pattern = Pattern.compile(patternString, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(text);
System.out.println("lookingAt = " + matcher.lookingAt());
System.out.println("matches   = " + matcher.matches());

上面的例子分别对文本开头和整个文本匹配正则表达式 “this is the”. 匹配文本开头的方法(lookingAt()) 返回true。

对整个文本匹配正则表达式的方法 (matches()) 返回false,因为 整个文本包含多余的字符,而 正则表达式要求文本精确匹配”this is the”,前后又不能有额外字符。

find() + start() + end()

find() 方法用于在文本中查找出现的正则表达式,文本是创建Matcher时,通过 Pattern.matcher(text) 方法传入的。如果在文本中多次匹配,find() 方法返回第一个,之后每次调用 find() 都会返回下一个。

start() 和 end() 返回每次匹配的字串在整个文本中的开始和结束位置。实际上, end() 返回的是字符串末尾的后一位,这样,可以在把 start() 和 end() 的返回值直接用在String.substring() 里。

String text    =        
"This is the text which is to be searched " +        
"for occurrences of the word 'is'.";
String patternString = "is";
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher(text);
int count = 0;while(matcher.find()) {
    count++;
    System.out.println("found: " + count + " : "  + matcher.start() + " - " + matcher.end());
    }

这个例子在文本中找到模式 “is” 4次,输出如下:

found: 1 : 2 - 4
 found: 2 : 5 - 7
 found: 3 : 23 - 25
 found: 4 : 70 - 72

reset()

reset() 方法会重置Matcher 内部的 匹配状态。当find() 方法开始匹配时,Matcher 内部会记录截至当前查找的距离。调用 reset() 会重新从文本开头查找。

也可以调用 reset(CharSequence) 方法. 这个方法重置Matcher,同时把一个新的字符串作为参数传入,用于代替创建 Matcher 的原始字符串。

group()

假设想在一个文本中查找URL链接,并且想把找到的链接提取出来。当然可以通过 start()和 end()方法完成。但是用group()方法更容易些。

分组在正则表达式中用括号表示,例如:

(John)

此正则表达式匹配John, 括号不属于要匹配的文本。括号定义了一个分组。当正则表达式匹配到文本后,可以访问分组内的部分。

使用group(int groupNo) 方法访问一个分组。一个正则表达式可以有多个分组。每个分组由一对括号标记。想要访问正则表达式中某分组匹配的文本,可以把分组编号传入 group(int groupNo)方法。

group(0) 表示整个正则表达式,要获得一个有括号标记的分组,分组编号应该从1开始计算。

String text    =  
"John writes about this, and John writes about that," +                        
" and John writes about everything. "  ;
String patternString1 = "(John)";
Pattern pattern = Pattern.compile(patternString1);
Matcher matcher = pattern.matcher(text);while(matcher.find()) {
    System.out.println("found: " + matcher.group(1));
    }

以上代码在文本中搜索单词John.从每个匹配文本中,提取分组1,就是由括号标记的部分。输出如下

found: John
 found: John 
 found: John

多分组

上面提到,一个正则表达式可以有多个分组,例如:

(John) (.+?)

这个表达式匹配文本”John” 后跟一个空格,然后跟1个或多个字符,最后跟一个空格。你可能看不到最后的空格。

这个表达式包括一些字符有特别意义。字符 点 . 表示任意字符。 字符 + 表示出现一个或多个,和. 在一起表示 任何字符,出现一次或多次。字符? 表示 匹配尽可能短的文本。

完整代码如下

String text    =          
"John writes about this, and John Doe writes about that," +                  
" and John Wayne writes about everything."
        ;
        String patternString1 = "(John) (.+?) ";
        Pattern pattern = Pattern.compile(patternString1);
        Matcher matcher = pattern.matcher(text);
        while(matcher.find()) {
                 System.out.println("found: " + matcher.group(1) +                      
                  " "       + matcher.group(2));
                  }

注意代码中引用分组的方式。代码输出如下

found: John writes 
found: John Doe 
found: John Wayne

嵌套分组

在正则表达式中分组可以嵌套分组,例如

((John) (.+?))

这是之前的例子,现在放在一个大分组里.(表达式末尾有一个空格)。

当遇到嵌套分组时, 分组编号是由左括号的顺序确定的。上例中,分组1 是那个大分组。分组2 是包括John的分组,分组3 是包括 .+? 的分组。当需要通过groups(int groupNo) 引用分组时,了解这些非常重要。

以下代码演示如何使用嵌套分组

String text    =          
"John writes about this, and John Doe writes about that," +                  
" and John Wayne writes about everything."
        ;
        String patternString1 = "((John) (.+?)) ";
        Pattern pattern = Pattern.compile(patternString1);
        Matcher matcher = pattern.matcher(text);
        while(matcher.find()) {
              System.out.println("found:   ");
              }

输出如下

found: 
 found: 
 found:

replaceAll() + replaceFirst()

replaceAll() 和 replaceFirst() 方法可以用于替换Matcher搜索字符串中的一部分。replaceAll() 方法替换全部匹配的正则表达式,replaceFirst() 只替换第一个匹配的。

在处理之前,Matcher 会先重置。所以这里的匹配表达式从文本开头开始计算。

示例如下

快写红薯通AI
快写红薯通AI

快写红薯通AI,专为小红书而生的AI写作工具

下载
String text    =          
"John writes about this, and John Doe writes about that," +                  
" and John Wayne writes about everything."
        ;
        String patternString1 = "((John) (.+?)) ";
        Pattern pattern = Pattern.compile(patternString1);
        Matcher matcher = pattern.matcher(text);
        String replaceAll = matcher.replaceAll("Joe Blocks ");
        System.out.println("replaceAll   = " + replaceAll);
        String replaceFirst = matcher.replaceFirst("Joe Blocks ");
        System.out.println("replaceFirst = " + replaceFirst);

输出如下

replaceAll = Joe Blocks about this, and Joe Blocks writes about that,and Joe Blocks writes about everything.
replaceFirst = Joe Blocks about this, and John Doe writes about that,and John Wayne writes about everything.

输出中的换行和缩进是为了可读而增加的。

注意第1个字符串中所有出现 John 后跟一个单词 的地方,都被替换为 Joe Blocks 。第2个字符串中,只有第一个出现的被替换。

appendReplacement() + appendTail()

appendReplacement() 和 appendTail() 方法用于替换输入文本中的字符串短语,同时把替换后的字符串附加到一个 StringBuffer 中。

当find() 方法找到一个匹配项时,可以调用 appendReplacement() 方法,这会导致输入字符串被增加到StringBuffer 中,而且匹配文本被替换。 从上一个匹配文本结尾处开始,直到本次匹配文本会被拷贝。

appendReplacement() 会记录拷贝StringBuffer 中的内容,可以持续调用find(),直到没有匹配项。

直到最后一个匹配项目,输入文本中剩余一部分没有拷贝到 StringBuffer. 这部分文本是从最后一个匹配项结尾,到文本末尾部分。通过调用 appendTail() 方法,可以把这部分内容拷贝到 StringBuffer 中.

String text    =          
"John writes about this, and John Doe writes about that," +                  
" and John Wayne writes about everything."
        ;
        String patternString1 = "((John) (.+?)) ";
        Pattern      pattern      = Pattern.compile(patternString1);
        Matcher      matcher      = pattern.matcher(text);
        StringBuffer stringBuffer = new StringBuffer();
        while(matcher.find()){
              matcher.appendReplacement(stringBuffer, "Joe Blocks ");
              System.out.println(stringBuffer.toString());
              }
matcher.appendTail(stringBuffer);
System.out.println(stringBuffer.toString());

注意我们在while循环中调用appendReplacement() 方法。在循环完毕后调用appendTail()。 代码输出如下:

Joe Blocks
 Joe Blocks about this, and Joe Blocks
 Joe Blocks about this, and Joe Blocks writes about that, and Joe Blocks
 Joe Blocks about this, and Joe Blocks writes about that, and Joe Blocks
 writes about everything.

Java 正则表达式语法

为了更有效的使用正则表达式,需要了解正则表达式语法。正则表达式语法很复杂,可以写出非常高级的表达式。只有通过大量的练习才能掌握这些语法规则。

Java 正则表达式语法

为了更有效的使用正则表达式,需要了解正则表达式语法。正则表达式语法很复杂,可以写出非常高级的表达式。只有通过大量的练习才能掌握这些语法规则。

本篇文字,我们将通过例子了解正则表达式语法的基础部分。介绍重点将会放在为了使用正则表达式所需要了解的核心概念,不会涉及过多的细节。详细解释,参见 Java DOC 中的 Pattern 类.

基本语法

在介绍高级功能前,我们先快速浏览下正则表达式的基本语法。

字符

是正则表达式中最经常使用的的一个表达式,作用是简单的匹配一个确定的字符。例如:

John

这个简单的表达式将会在一个输入文本中匹配John文本。

可以在表达式中使用任意英文字符。也可以使用字符对于的8进制,16进制或unicode编码表示。例如:

101\x41\u0041

以上3个表达式 都表示大写字符A。第一个是8进制编码(101),第2个是16进制编码(41),第3个是unicode编码(0041).

字符分类

字符分类是一种结构,可以针对多个字符匹配而不只是一个字符。换句话说,一个字符分类匹配输入文本中的一个字符,对应字符分类中多个允许字符。例如,你想匹配字符 a,b 或c,表达式如下:

[abc]

用一对方括号[] 表示字符分类。方括号本身并不是要匹配的一部分。

可以用字符分类完成很多事。例如想要匹配单词John,首字母可以为大写和小写J.

[Jj]ohn

字符分类[Jj] 匹配J或j,剩余的 ohn 会准确匹配字符ohn.

预定义字符分类

正则表达式中有一些预定义的字符分类可以使用。例如, \d 表示任意数字, \s 表示任意空白字符,\w 表示任意单词字符。

预定义字符分类不需要括在方括号里,当然也可以组合使用

\d[\d\s]

第1个匹配任意数字,第2个匹配任意数字或空白符。

完整的预定义字符分类列表,在本文最后列出。

边界匹配

正则表达式支持匹配边界,例如单词边界,文本的开头或末尾。例如,\w 匹配一个单词,^匹配行首,$ 匹配行尾。

^This is a single line$

上面的表达式匹配一行文本,只有文本 This is a single line。注意其中的行首和行尾标志,表示不能有任何文本在文本的前面后后面,只能是行首和行尾。

完整的匹配边界列表,在本文最后列出。

量词匹配

量词可以匹配一个表达式多次出现。例如下列表达式匹配字母A 出现0次或多次。

A* 
量词 * 表示0次或多次。+ 表示1次或多次。? 表示0次或1次。还有些其他量词,参见本文后面的列表。

量词匹配分为 饥饿模式,贪婪模式,独占模式。饥饿模式 匹配尽可能少的文本。贪婪模式匹配尽可能多的文本。独占模式匹配尽可能多的文本,甚至导致剩余表达式匹配失败。

以下演示饥饿模式,贪婪模式,独占模式区别。假设以下文本:

John went for a walk, and John fell down, and John hurt his knee. 
饥饿模式下 表达式:

John.*?

这个表达式匹配John 后跟0个或多个字符。 . 表示任意字符。* 表示0或多次。? 跟在 * 后面,表示 * 采用饥饿模式。

饥饿模式下,量词只会匹配尽可能少的字符,即0个字符。上例中的表达式将会匹配单词John,在输入文本中出现3次。

如果改为贪婪模式,表达式如下:

John.*

贪婪模式下,量词会匹配尽可能多的字符。现在表达式会匹配第一个出现的John,以及在贪婪模式下 匹配剩余的所有字符。这样,只有一个匹配项。

最后,我们改为独占模式:

John.*+hurt

*后跟+ 表示独占模式量词。

这个表达式在输入文本中没有匹配项,尽管文本中包括 John 和 hurt. 为什么会这样? 因为 .*+ 是独占模式。与贪婪模式下,尽可能多的匹配文本,以使整个表达式匹配不同。独占模式会尽可能的多的匹配,但不考虑表达式剩余部分是否能匹配上。

.*+ 将会匹配第一个John之后的所有字符,这会导致表达式中剩余的 hurt 没有匹配项。如果改为贪婪模式,会有一个匹配项。表达式如下:

John.*hurt

逻辑操作符

正则表达式支持少量的逻辑运算(与,或,非)。

与操作是默认的,表达式 John ,意味着J 与 o与h与n。

或操作需要显示指定,用 | 表示。例如表达式 John|hurt 意味着John 或 hurt 。

字符

2330.jpg

2331.jpg

字符分类

2332.jpg

内置字符分类 

2333.jpg

边界匹配 

2334.jpg

量词

2335.jpg


相关文章

java速学教程(入门到精通)
java速学教程(入门到精通)

java怎么学习?java怎么入门?java在哪学?java怎么学才快?不用担心,这里为大家提供了java速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

相关标签:

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
chatgpt使用指南
chatgpt使用指南

本专题整合了chatgpt使用教程、新手使用说明等等相关内容,阅读专题下面的文章了解更多详细内容。

0

2026.03.16

chatgpt官网入口地址合集
chatgpt官网入口地址合集

本专题整合了chatgpt官网入口地址、使用教程等内容,阅读专题下面的文章了解更多详细内容。

0

2026.03.16

minimax入口地址汇总
minimax入口地址汇总

本专题整合了minimax相关入口合集,阅读专题下面的文章了解更多详细地址。

4

2026.03.16

C++多线程并发控制与线程安全设计实践
C++多线程并发控制与线程安全设计实践

本专题围绕 C++ 在高性能系统开发中的并发控制技术展开,系统讲解多线程编程模型与线程安全设计方法。内容包括互斥锁、读写锁、条件变量、原子操作以及线程池实现机制,同时结合实际案例分析并发竞争、死锁避免与性能优化策略。通过实践讲解,帮助开发者掌握构建稳定高效并发系统的关键技术。

7

2026.03.16

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

114

2026.03.13

Python异步编程与Asyncio高并发应用实践
Python异步编程与Asyncio高并发应用实践

本专题围绕 Python 异步编程模型展开,深入讲解 Asyncio 框架的核心原理与应用实践。内容包括事件循环机制、协程任务调度、异步 IO 处理以及并发任务管理策略。通过构建高并发网络请求与异步数据处理案例,帮助开发者掌握 Python 在高并发场景中的高效开发方法,并提升系统资源利用率与整体运行性能。

141

2026.03.12

C# ASP.NET Core微服务架构与API网关实践
C# ASP.NET Core微服务架构与API网关实践

本专题围绕 C# 在现代后端架构中的微服务实践展开,系统讲解基于 ASP.NET Core 构建可扩展服务体系的核心方法。内容涵盖服务拆分策略、RESTful API 设计、服务间通信、API 网关统一入口管理以及服务治理机制。通过真实项目案例,帮助开发者掌握构建高可用微服务系统的关键技术,提高系统的可扩展性与维护效率。

396

2026.03.11

Go高并发任务调度与Goroutine池化实践
Go高并发任务调度与Goroutine池化实践

本专题围绕 Go 语言在高并发任务处理场景中的实践展开,系统讲解 Goroutine 调度模型、Channel 通信机制以及并发控制策略。内容包括任务队列设计、Goroutine 池化管理、资源限制控制以及并发任务的性能优化方法。通过实际案例演示,帮助开发者构建稳定高效的 Go 并发任务处理系统,提高系统在高负载环境下的处理能力与稳定性。

65

2026.03.10

Kotlin Android模块化架构与组件化开发实践
Kotlin Android模块化架构与组件化开发实践

本专题围绕 Kotlin 在 Android 应用开发中的架构实践展开,重点讲解模块化设计与组件化开发的实现思路。内容包括项目模块拆分策略、公共组件封装、依赖管理优化、路由通信机制以及大型项目的工程化管理方法。通过真实项目案例分析,帮助开发者构建结构清晰、易扩展且维护成本低的 Android 应用架构体系,提升团队协作效率与项目迭代速度。

111

2026.03.09

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.5万人学习

C# 教程
C# 教程

共94课时 | 11.5万人学习

Java 教程
Java 教程

共578课时 | 83.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号