ICode9

精准搜索请尝试: 精确搜索
首页 > 编程语言> 文章详细

Java 学习 - 正则表达式

2020-11-02 15:33:00  阅读:238  来源: 互联网

标签:字符 量词 Java 正则表达式 模式 学习 匹配 文本


Java 学习 - 正则表达式

一.设计正则表达式的目的

正则表达式使用单个字符串来描述,匹配一系列匹配某个句法规则的字符串.在很多文本编辑器里,正则表达式通常被用来检索,替换那些匹配某个模式的文本. 许多程序设计语言都支持利用正则表达式进行字符串操作.与其说正则表达式是一个Java的库,倒不如说正则表达式是一个针对于字符串处理的语言.

二.正则表达式基本语法

在介绍正则表达式在Java中的使用方法之前,我们先介绍正则表达式的匹配方式. 毕竟,正则表达式并非Java所特有,应该更加注重正则表达式的功能,而非在Java中具体的实现方法.

模式串与文本串的概念

正则表达式用于判定文本串是否与给定的模式串匹配.这里介绍一下文本串与模式串的概念:

  • 模式串是一个遵循某种规则的泛化的字符串, 其某些字符,字符串的长度可能不尽相同,一个模式串可能能够表示多种不同的文本串.
  • 文本串是一个固定的字符串,文本串的每一个字符都是确定的.

模式串的格式

1.单个字符是一个模式串

image-20201102120934256

2.一个字符集是一个模式串

字符集的作用是检验由单个字符所构成的文本串是否与字符集中的字符满足一定关系

- 属于(simple classes)

[abc] // 可以匹配的文本串: "a","b","c"

- 不属于(negation)

[^abc] // 可以匹配的文本串: 除了"a","b","c"的任意单个字符

- 属于某一范围(range)

[a-zA-Z] // 可以匹配的文本串: "a" ~ "z" ,"A"~"Z" 任意单个字符 

- 属于并集(union)

[a-d[m-p]] // 可以匹配的文本串: "a"~"d" ,"m" ~ "p" 任意单个字符 

这里我有一点疑虑: union和range的区别是什么? 等后期更加理解后补充进来.

- 属于交集(intersection)

[a-z&&[def]] // 可以匹配的字符串: [a-z] 和 [def] 取交集是[def],因此能够匹配 "d","e","f"

- 属于差集(subtraction)

[a-z&&[^m-p]] // 可以匹配的字符串: [a-z] 和 [^m-p]取交集是 [a-l][q-z],因此能够匹配"a"~"l","q"~"z" 
image-20201102122802403

此外,Java中还提供一些被预定义好的字符集

image-20201102124637027 image-20201102124830935

还有一些预定义字符集看起来不太常用,这里不再介绍.

3.包含边界匹配器的模式串

所谓边界匹配器,其实是对一个模式串增添一些附加条件,例如"出现在文本串的开头","出现在文本串的结尾"

明确一个观念对于理解边界匹配器有很大的帮助

边界匹配器的宽度为0,不影响模式串的长度;或者说,包含边界匹配器的模式串长度与剔除边界匹配器的模式串长度应当一致

常见的边界匹配器:

image-20201102130107364

示例

  • ^ 匹配文本串的开头

模式串

"^HelloWorld" // 所匹配的文本串: "HelloWorld"的部分,且必须满足"HelloWorld"在整个串的开头

匹配示例

#case1: "HelloWorld" // 匹配出 "HelloWorld"
#case2: "HeheHelloWorld" // 无匹配
#case3: "HelloWorldHehe" // 匹配出 "HelloWorld"

一个无意义的匹配:

"HelloWorld^" // 由于^匹配出文本串的开头位置,而"HelloWorld"永远不可能在开头位置之前,因此这个模式串永远不可能匹配成功
  • $ 匹配文本串的结尾

模式串

"HelloWorld$" // 所匹配的文本串

匹配示例

#case1: "HeheHelloWorld" // 匹配出 "HelloWorld"
#case2: "HelloWorldHehe" // 无匹配
#case3: "HelloWorld" // 匹配出"HelloWorld"

一个无意义的匹配:

"$HelloWorld"  // 由于$匹配出文本串的开头位置,而"HelloWorld"永远不可能在结尾位置之后,因此这个模式串永远不可能匹配成功
  • \b 匹配单词边界

单词边界的意义是: 一侧为单词字符,另一侧为非单词字符. 其中单词字符包括[字母,数字,下划线,汉字],非单词字符还包括空字符.

模式串

\bapple

匹配示例

#case1: "apple"  // 匹配出apple,因为a是一个单词字符,而a左边是一个空字符,\b的两侧满足一个为非单词字符,一个为单词字符
#case2: "bapple" // 无匹配,因为 \b的两侧为'b'和'a',均为非单词字符
#case3: " apple" // 匹配出"apple",因为\b的两侧分别为' '和'a'
#case4: "apple123456" 
// 匹配出apple,因为a是一个单词字符,而a左边是一个空字符,\b的两侧满足一个为非单词字符,一个为单词字符,而后续的"123456"不影响结果
#case5: " app" // 无匹配,虽然\b的两侧为' '和'a',但后续的"apple"无匹配

两个无意义的匹配

" \b apple"  // 因为\b两侧已经指定了必须为' '和' ',而它们都是非单词字符,不满足\b的条件,因此永远无法匹配成功
"a\bapple"   // 因为\b两侧已经指定了必须为'a'和'a',而它们都是单词字符,不满足\b的条件,因此永远无法匹配成功

4.包含贪婪量词的模式串(有回溯贪婪量词)

贪婪量词的"贪婪"意义: 尽可能地多匹配字符;如果一个字符串满足要求,继续向后检测,是否仍然符合要求,如果仍符合要求则继续匹配

应当注意的是,"满足要求"并非指仅仅满足X部分的要求,而是使得全局满足要求

贪婪量词的使用十分广泛,先看贪婪量词的常见类型

image-20201102140628285
  • X? 表达可选择

模式串

"\d(.\d)?"

匹配示例

#case1: "1" // 匹配出"1"
#case2: "1.5" // 匹配出"1.5"
#case3: "1.25" // 匹配出"1.2"和"5" 
#case4: "13.2" // 匹配出"1"和"3.2"
#case4: ".25" // 匹配出"2"和"5"
  • X* 表达任意次

关于X*的用法,千万不要看网上大多数中文的翻译"零次或多次",这容易造成误解"一次不出现或出现次数至少为2". 官方文档给的定义是"zero or more times",表示的是可以出现任意次.

模式串

"xo*"

匹配示例

#case1: "x" // 匹配"x"
#case2: "xo" // 匹配"xo"
#case3: "xooo" // 匹配"xooo"
  • X+ 表达至少出现一次

这个用法比较浅显易懂,不再举例

  • X{n}

出现次数恰好为n

  • X{n,}

出现次数至少为n

  • X{n,m}

出现次数至少为n,至多为m

模式串

"xo{1,3}"

文本串

#case1: "x" // 无匹配
#case2: "xo" // 匹配出"xo"
#case3: "xoo" // 匹配出"xoo"
#case4: "xooo" // 匹配出"xooo"
#case5: "xoooo" // 匹配出"xooo"

5.包含节制量词的模式串

节制量词的"节制"意义: 尽可能地少匹配字符;如果一个字符串满足要求,立刻返回匹配的串,即使后续有更长的字符串,也不再匹配.

应当注意的是,"满足要求"并非指仅仅满足X部分的要求,而是使得全局满足要求

例如

模式串

"<a.*?>"

匹配

#case1: "<abbbb>" // 匹配出"<abbbb>"而非"<ab>". 表面上,这是因为"<ab>"本身并非文本串"<abbbb>"的连续子串;而如果从节制量词的实现方式来考虑,节制量词要求满足"<a.*?>"的全局要求,而非".*"的局部要求.

在贪婪量词的后面加'?'表达节制含义

image-20201102143515698

6.包含占有量词的模式串(无回溯贪婪量词)

这个量词相对用的比较少,而且我上网查一些在线的正则测试工具,似乎并不支持占有量词

对于占有量词,应该结合其与贪婪量词的区别来理解.

模式串

"<ab*>" // 贪婪量词
"<ab*+>" // 占有量词

匹配示例

#case1: "<abbbbb>" // 贪婪量词匹配出"<abbbbb>",占有量词无匹配
贪婪量词 非贪婪量词 占有量词 匹配
X? X?? X?+ 匹配X 0次或1次
X* X*? X*+ 匹配X 0次或无数次
X+ X+? X++ 匹配X 1次或无数次
X{n} X{n}? X{n}+ 匹配X n次
X{n,} X{n,}? X{n,}+ 匹配X 至少n次
X{n,m} X{n,m}? X{n,m}+ 匹配X 至少n次至多m次

7.包含捕获组的模式串

 组和捕获
捕获组可以通过从左到右计算其开括号来编号,在表达式 ((A)(B(C))) 中,可以理解为bfs的过程
$1    =	((A)(B(C)))
$2    = (A)
$3    =	(B(C))
$4    =	(C)

image-20201102151116692

实际上,刚刚我们已经多次使用了捕获组,它和数学上括号的意义相同,即划分整体以及改变运算优先级

8. 包含逻辑运算符的模式串

image-20201102151021827

剩下还有一些更加高级的操作,不再介绍.基本的正则表达式匹配语法介绍到此为止.

三.Java中使用正则表达式

引用

  1. Class Pattern
  2. 正则表达式之字符边界

标签:字符,量词,Java,正则表达式,模式,学习,匹配,文本
来源: https://www.cnblogs.com/popodynasty/p/13914698.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有