正则表达式

本文内容非原创,你可以点击此处查看内容来源声明

正则表达式用于指定字符串的模式,可以在任何需要定匹配某种特定某种特定模式的字符串的情况下使用正则表达式。

在使用正则表达式的各种程序和类库之间,表达式语法并未完全标准化。尽管在基本结构上达成了一致,但是它们之间仍旧存在着许多差异。Java正则表达式类使用的语法与Perl语言使用的语法十分相似,但是并不完全一样。关于正则表达式的更多信息,可以参考《Mastering Regualr Express》.

正则表达式的最简单用法是测试某个特定的字符串是否与它匹配。

下面展示了如何用Java来编写这种测试,首先用正则表达式的字符串构建一个Pattern对象,然后从这个模式中获得一个Matcher,并调用他的matches方法。
Pattern pattern = Pattern.compile(patternString);
Matcher matcher = pattern.matcher(input);
if(matcher.matches()) ...

这个匹配器的输入可以是任何实现了CharSequence接口的类的对象,例如String,StringBuilder,StringBuffer.
在编译这个模式时,可以设置一个或多个标志,例如:
Pattern pattern = Pattern.compile(expression,Pattern.CASE_INTENSIVE + Pattern.UNICODE_CASE);
或者可以在模式中指定它们:
String regex = "(?iU:expression)";
下面是各个标志:

  • Pattern.CASE_INSENSITIVE或r:匹配字符时忽略字母大小写,默认情况下,这个标志只考虑US ASCII字符。
  • Pattern.UNICODE_CASE或u: 当有CASE_INSENSITIVE组合使用时,用Unicode字母的大小写来匹配。
  • Pattern.UNICODE_SHARACTER_CLASS或U:选择Unicode字符类代替POSIX,其中蕴含了UNICODE_CASE;
  • Pattern.MULTILINE或m: ^和$匹配行的开头和结尾,而不是整个输入的开头和结尾。
  • Pattern.UNIX_LINES或d: 在多行模式中匹配^和$时,只有'\n'被识别成行终止符。
  • Pattern.DOTALL或s: 当使用这个标志时,.符号匹配所有字符,包括行终止符。
  • Pattern.LITERAL: 该模式将逐字地采纳,必须精确匹配,因字母大小写而造成的差异除外。
  • Pattern.CANON_EQ: 考虑Unicode字符规范的等价性,例如,u后面跟``(分音符号)匹配
    u:(a o e i u v 的v )

最后两个标志不能在正则表达式内部指定。
如果想要在集合或流中匹配元素,可以将模式转换为谓词:
Stream<String> strings = ...;
Stream<String> result = strings.fiter(pattern.asPredicate());
其结果中包含了匹配正则表达式的所有字符串。

如果正则表达式包含群组,那么Matcher对象可以揭示群组的边界。下面的方法
int start(int groupIndex)
int end(int groupIndex)
将产生指定群组的开始索引和结束之后的索引。

可以直接通过调用下面的方法抽取匹配的字符串:
String group(int groupIndex)

群组0 是整个输入,而用于第一个实际群组的群组索引是1。调用groupCount方法可以获得全部群组的数量。对于具名的组,使用下面的方法:
int start(String groupName)
int end(String groupName)
String group(String groupName)

嵌套群组是按照前括号排序的,例如,假设有下面的模式
(([1-9]|1[0-2]):([0-5][0-9]))[ap]m
和下面的输出
11:59am
那么,匹配器会报告下面的群组:

群组索引 开始 结束 字符串
0 0 7 11:59am
1 0 5 11:59
2 0 2 11
3 3 5 59

通常,不希望用正则表达式匹配全部输入,只是想找出输入中一个或多个匹配的子字符串。这时可以使用Matcher类的find方法来查找匹配内容,如果返回true,在使用start和end方法来查找匹配的内容,或使用不带引元的group方法来获取匹配的字符串。
whiel(matcher.find()){
int start = matcher.start();
int end = matcher.end();
String match =input.group();
...}

Matcher类的replaceAll方法将正则表达式出现的所有地方都用替换字符串来替换。
替换字符串可以包含对模式中群组的引用:n表示替换成第n个群组,{name}被替换为具有给定名字的组,因此我们需要用$来表示在替换文本中包含一个字符。 如果字符串中包含和,但是又不希望它们被解释成群组的符,那么就可以调用matcher.replaceAll(Matcher.quoteReplacement(str)).

replaceFirst方法将只替换模式的第一次出现。

最后,Pattern类有一个split方法,它可以用正则表达式来匹配边界,从而将输入分割成字符串数组。

附录:正则表达式语法

表达式 描述 示例
字符
c,除.*+?{|()[^$之外 字符c ]
. 任何行终止符之外的字符,或者在DOTALL标志被设置时表示任何字符
\x{p} 十六进制码为p的Unicode码点 \x{1D546}
\uhhhh,\xhh,\0o,\0oo,\0ooo 具有给定十六进制或八进制值的码元 \uFEFF
\a,\e,\f,\n,\r,\t 响铃符(\x{7}),转义符(\x{18}),换页符(\x{8}),换行符(\x{A})、回车符(\s{D}),指标符(\x{9}) \n
\cc,其中c在[A,Z]的范围内,或者是@[]^_?之一 对应于字符c的控制字符 \cH是退格符(\x{8})
\c,其中c不在[A-Za-z0-9]的范围内 字符c \\
\Q...\E 在左引号和右引号之间的所有字符 \Q(...)\E匹配字符串(...)
字符类
C1C2...],其中C1是多个字符,范围从c-d,或者是字符类 任何由C1,S2...表示的字符 [0-9+-]
[^...] 某个字符类的补集 [^\d\s]
[...&&...] 字符集的交集 [\p{L}&&[^A-Za-a]]
\p{...},\P{...} 某个预定义字符类;他的补集 \p{L}匹配一个Unicode字母,而\pL也匹配这个字母,可以忽略单个字母情况下的括号
\d,\D 数字[0-9],或者在UNICODE_CHARACTER_CLASS标志被设置时表示\p{Digit});它的补集 \d+是一个数字序列
\w,\W 单词字符([z-zA-Z09]),或者在UNICODE_CHARACTER_CLASS标志被设置时表示Unicode单词字符;他的补集
\s,\S 空([ \n\r\t\f\x{8}],或者在UNICODE_CHARACTER_CLASS标志被设置时表示\p{IsWhite_Space});它的补集 \s,\s是由可选的空格字符包围的逗号
\h,\v,\H,\V 水品空白字符、垂直空白字符、他们的补集
序列和选择
XY 任何X中的字符串,后面跟随任何Y中的字符串 [1-9][0-9]*表示没有前导零的正整数
X|Y 任何X或Y中的字符串
群组
(X) 捕获X的匹配 '([^']*)'捕获的是被引用的文本
\n 第n组 (['"]).*\1可以匹配'Fred'和"Fred",但是不能匹配”Fred'
(?<name>X) 捕获与给定名字匹配的X '(?<id>[A-Za-z0-9]+)'可以捕获名字为id的匹配
k<name> 具有给定名字的组 \k<id>可以匹配名字为id的组
(?:X) 使用括号但不捕获X 在(?:http|ftp)://(.*)中,在://之后匹配的是\1
(?f1f2...:X)
(?f1...-fk...:X),其中fi在后[dismsuUx]的范围中
匹配但是不捕获给定标志开或关(在-之后)的X (?i:jpe?g)是大小写不敏感的匹配
其他(?...) 参阅Pattern API 文档
量词
X? 可选X +?是可选的+号
X*,X+ 0或多个X,1或多个X [1-9][0-9]是+是大于10的整数
X{n},X{n,},X{m,n} n个X。 [0-7]{1,3}是一位到三位的八进制数
Q?,其中Q是一个量词表达式 勉强量词,在尝试最长匹配之前先尝试最短匹配 .(<.+?>).捕获尖括号括起来的最短序列
Q+,,其中Q是一个量词表达式 占有量词,在不回溯情况下获取最长匹配 '[^']*+'匹配单括号引起来的字符串,并且在字符串中没有右单引号的情况下立即匹配失败
边界匹配
^,$ 输入的开头和结尾(或者多行模式的开头和结尾行) ^Java$匹配输入中的Java或Java构成的行
\A,\Z,\z 输入的开头,输入的结尾、输入的绝对结尾(在多行模式中不会发生变化)
\b,\B 单词边界,非单词边界 \bJava b匹配单词Java
\R Unicode行分隔符
\G 前一个匹配的结尾

与-p一起使用的预定义字符类名字

字符类名字 解释
posixClass posixClass是Lower,Upper,Alpha,Digit,Alnum,Punct,Graph,Print,Cntrl,XDigit,Space,Blank,ASCII之一,它会依UNICODE_CHARACTER_CLASS标志的值而被解释成POSIX或Unicode类。
IsScript, sc=script,script=Script Character.UnicodeScript.forName可以接受的脚本
InBlock,blk=Block,block=Block Character.UnicodeScript.forName可以接受的块
Category,InCategory,gc=Category,general_category=Category Unicode通用分类的单字母或双字母名字
IsProperty Property是Alphabetic,Ideographic,Letter,Lowercase,Uppercase,Titlecase,Punctuation,Control,White_Space,Digit,Hex_Digit,Join_Control,Noncharacter_Code_Point,Assigned之一
javaMethod 调用Character.isMethod方法(必须不是过时的方法)
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,406评论 6 503
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,732评论 3 393
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 163,711评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,380评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,432评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,301评论 1 301
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,145评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,008评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,443评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,649评论 3 334
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,795评论 1 347
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,501评论 5 345
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,119评论 3 328
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,731评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,865评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,899评论 2 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,724评论 2 354

推荐阅读更多精彩内容

  • python的re模块--细说正则表达式 可能是东半球最详细最全面的re教程,翻译自官方文档,因为官方文档写的是真...
    立而人阅读 22,875评论 4 46
  • 1.正则表达式介绍 正则表达式算起来也是一个很庞大的语言系统,在所有的开发语言中基本都支持正则表达式,它可以很方便...
    babybus_superdo阅读 2,570评论 3 6
  • Java的正则表达式讲解:(为了能看清,本文正则表达式用中文的句号代替英文句点) 英文句点符号:匹配单个任意字符。...
    红姑娘阅读 4,356评论 0 2
  • 瓣落香浸桃花酒,双眸添红,掩笑拂春柳。 卷动疏帘且回首,窗外莺歌几时休。 知更呼晴凉雨后,何处闲愁,尽藏相思袖。 ...
    那个男人_dc48阅读 435评论 0 1
  • 我这人有个致命的毛病——爱拖延,不到最后关头绝不行动。我总是以为时间多的很,今天做不完怕什么,还有明天,明...
    江南时光阅读 179评论 0 2