原文发于http://blog.thihy.info/post/119,转载请注明出处。
本文是在学习正则表达式过程中整理的,虽然冠以“教程”,但实际上应该算是学习笔记。整篇文章需要对正则有一定的理解。。如果有啥写得不对的,或者写得不够清楚的,欢迎大家留言讨论。
概述
正则表达式(Regular Expression)是高效的、便捷的文本处理工具,能够快速查询符合某种规范的文本。
例如:[0-9]{3}
可以匹配3位数字,[a-z]{3}
则可以匹配3个小写字母。
目前正则表达式被众多工具所支持,比如egrep、sed、perl、ruby、Java、C#、python、Tcl等,不同的工具下,正在表达式的范式可能会有略微的差别,执行引擎也可能不同。目前,正则引擎主要有:DFA, 传统型NFA, POSIX NFA, DFA/NFA混合。本文主要介绍Java正则表达式,它的引擎属于传统型NFA。
Java正则支持Unicode,它在适当的时候,会使用java.lang.Character.codePointAt(CharSequence seq, int index)
获取Code Point
,而不是char。
构造方法
Java中的正则表达式的构造方法可以看Pattern的javadoc文档。
字符
对于可见字符,可以直接编写,这没啥难点。对于其它难以描述的字符,Java提供了一些表示方法。
字符缩略表示法
Java执行使用\x
来代表特殊的含义,有:
\\
\t
\n
\r
\f
\a
\e
\v
控制字符: \cchar
Java可以使用\cchar
匹配控制字符。其中char
的值为64 ^ 控制字符
,比如对于退格符(‘\b
‘),其ASCII码为8,则char
为64 ^ 8 = 72
,也即H
(H的ASCII码为72)。简单地,对于ASCII码小于64的控制字符,char
为控制字符的ASCII码加上64。
八进制表示:\0n
, \0nn
, \0mnn
Java中,八进制表示必须以\0开始(防止与反向引用混淆),这点可能与其他工具不同(某些工具有规则来区分反向引用和八进制)。\0后面的部分最多只能有3个数字,而n必须在区间[0,7]内,m必须在[0,3]内,所以最大表示\0377。
十六进制表示:\xhh
十六进制后面必须是两个十六进制字符,也即h必须是0~9,a-f或A-F。\x00和\xff都是合法的,但是\xa,\x0ab,\x1g都是不合法的。
Unicode转义:\uhhhh
Unicode转义的形式与十六进制类似,只是后面必须是四个六进制字符。
行结束符
行结束符是用来标记输入字符序列的行结尾,可能有一个或两个字符。在Java中,行结束符包括:
- 新行(换行)符 (‘\n’)
- 后面紧跟新行符的回车符 (“\r\n”)
- 单独的回车符 (‘\r’)
- 下一行字符 (‘\u0085′)
- 行分隔符 (‘\u2028′)
- 段落分隔符 (‘\u2029)
如果启用了UNIX_LINES模式,则新行符(即’\n’)是惟一识别的行结束符。
只有启用DOTALL标志,正则表达式中的点号(即’.')才会匹配行结束符。
默认情况下,正则表达式^和$会忽略行结束符,仅分别与整个输入序列的开头和结尾匹配。如果激活 MULTILINE 模式,则 ^ 在输入的开头和行结束符之后(输入的结尾)才发生匹配。处于 MULTILINE 模式中时,$ 仅在行结束符之前或输入序列的结尾处匹配。
字符类
字符类: [...]
字符类的形式是[...]
,其内部可以是若干字符,也可以是一个字符范围。比如[a]表示匹配a字符,[a-z]表示匹配所有小写的英文字母。字符范围中的字符可以是Unicode字符,并且不要求是同一类的,也即[a-}]
也是可以的,甚至是[a-星]
。
字符类集合运算
字符类可以进行补集、并集(隐式)、交集和差集的运算。所有的集合运算都必须在字符类内部实现。
^
开头,则表示是一个补集。比如[^a]表示匹配不是a的所有字符,这与[a^]是不同的,后者表示匹配a字符或^字符。既然是补集,那么需要明确全集是什么。由于Java是支持Unicode的,所以全集是所有的Unicode字符。也即[^a]可以匹配汉字字符。注:很多书籍上(包括JavaDoc)都没有谈到补集的概念,而是作为基本的字符类,但我觉得成为补集操作更加便于理解。
&&
。例如[[1-5]&&[3-9]]等价于[3-5]。通过环视功能可以模拟交集运算,比如(?=[1-5])[3-9]
和[3-9](?<=[1-5])
都等价于[3-5]。(?![3-5])[0-9]
和[0-9](?<![3-5])
都等价于[0-26-9]。Java在解析字符类时,会按照如下的次序依次执行:
- 字面值转义 \x
- 分组 [...]
- 范围 a-z
- 并集 [a-e][i-u]
- 交集 [a-z&&[aeiou]]
- 补集 [^...]
点号:.
点号可以用来匹配除了行结束符之外的任意字符。但是,如果启用了DOTALL标志,则可以匹配行结束符。
1
2
3
|
// (?s)会启用DOTALL标志 assertEquals( true , "\n" .matches( "(?s)." ));
assertEquals( true , "\r" .matches( "(?s)." ));
|
字符类简记法:
Java预定义了如下几种字符组,可以很方便地使用。
-
\d
数字:[0-9] -
\D
非数字:[^0-9] -
\s
空白字符:[ \t\n\x0B\f\r] (注意第一个字符是空格) -
\S
非空白字符:[^\s] -
\w
单词字符:[a-zA-Z_0-9] -
\W
非单词字符:[^\w]
Unicode属性和区块:\p{PropOrBlock
、\P{PropOrBlock
\p{PropOrBlock
表示匹配符合PropOrBlock的所有字符,大写的\P{PropOrBlock
则匹配不符合PropOrBlock的所有字符。
PropOrBlock包括字符属性(Char Property)和区块(Block)。区块必须以In
开头,字符属性可以以Is
开头(可选)。Unicode 区块的定义在java.lang.Character.UnicodeBlock
,具体可以查看Unicode标准。字符属性的定义在java.util.regex.Pattern.CharPropertyNames
。
\p{InBASIC_LATIN} | Basic Latin |
\p{InCJK_COMPATIBILITY} | 中日韩兼容文字 |
更多请查看JavaDoc |
\p{ASCII} | ASCII字符: 0×00~0x7F |
\p{Lower} | 小写字母([a-z]) |
\p{Upper} | 小写字母([A-Z]) |
\p{Punct} | ASCII标点符号 |
\p{Alpha} | ASCII字母([a-zA-Z]) |
\p{Digit} | 数字([0-9] |
\p{Alnum} | ASCII字母和数字: [a-zA-Z0-9]) |
\p{Graph} | ASCII可打印(可见)字符: [\p{Alnum}\p{Punct}] |
\p{Blank} | ASCII Blank字符(空格和Tab字符) |
\p{Cntrl} | ASCII控制字符([\x00-\x1F\x7F]) |
\p{Print} | 可打印字符(0×20~0x7E) |
\p{Space} | ASCII Space字符([ \t\n\x0B\f\r]) |
\p{XDigit} | ASCII十六进制字符([0-9a-fA-F]) |
\p{javaLowerCase} | 等效于 java.lang.Character.isLowerCase() |
\p{javaUpperCase} | 等效于 java.lang.Character.isUpperCase() |
\p{javaTitleCase} | 等效于 java.lang.Character.isTitleCase() |
\p{javaDigit} | 等效于 java.lang.Character.isDigit() |
\p{javaDefined} | 等效于 java.lang.Character.isDefined() |
\p{javaLetter} | 等效于 java.lang.Character.isLetter() |
\p{javaLetterOrDigit} | 等效于 java.lang.Character.isLetterOrDigit() |
\p{javaJavaIdentifierStart} | 等效于 java.lang.Character.isJavaIdentifierStart() |
\p{javaJavaIdentifierPart} | 等效于 java.lang.Character.isJavaIdentifierPart() |
\p{javaUnicodeIdentifierStart} | 等效于 java.lang.Character.isUnicodeIdentifierStart() |
\p{javaUnicodeIdentifierPart} | 等效于 java.lang.Character.isUnicodeIdentifierPart() |
\p{javaIdentifierIgnorable} | 等效于 java.lang.Character.isIdentifierIgnorable() |
\p{javaSpaceChar} | 等效于 java.lang.Character.isSpaceChar() |
\p{javaISOControl} | 等效于 java.lang.Character.isISOControl() |
\p{javaWhitespace} | 等效于 java.lang.Character.isWhitespace() |
\p{javaMirrored} | 等效于 java.lang.Character.isMirrored() |
\p{L} | Letter: 字母 |
\p{M} | Mark: 标记字符,不能单独出现,必须与其他基本字符同时出现(如重音符号)。 |
\p{N} | Number: 各种数字字符 |
\p{Z} | Separator: 分隔字符,但是本身不可见(比如空格) |
\p{P} | Punctuation: 标点符号 |
\p{S} | Symbol: 各种图形符号和字母符号 |
\p{C} | Other: 其他任何字符 |
\p{Ll} | Character.LOWERCASE_LETTER: 小写字母 |
\p{Lu} | Character.UPPERCASE_LETTER: 大写字母 |
\p{Lt} | Character.TITLECASE_LETTER: 出现在单词开头的字母 |
\p{Lm} | Character.MODIFIER_LETTER: 少数形似字母的,有特别用途的字符 |
\p{Lo} | Character.OTHER_LETTER: 没有大小写形式,也不属于修饰符的字母。 |
\p{LC} | L1,Lu,Lt |
\p{LD} | LC,Lm,Lo,Nd |
\p{L1} | Latin-1(0×00~0xff) |
\p{Mn} | Character.NON_SPACING_MARK |
\p{Mc} | Character.COMBINING_SPACING_MARK |
\p{Me} | Character.ENCLOSING_MARK |
\p{Nd} | Character.DECIMAL_DIGIT_NUMBER |
\p{Nl} | Character.LETTER_NUMBER |
\p{No} | Character.OTHER_NUMBER |
\p{Zs} | Character.SPACE_SEPARATOR |
\p{Zl} | Character.LINE_SEPARATOR |
\p{Zp} | Character.PARAGRAPH_SEPARATOR |
p{Cc} | Character.CONTROL |
p{Cf} | Character.FORMAT |
p{Co} | Character.PRIVATE_USE |
p{Cs} | Character.SURROGATE |
p{Pd} | Character.DASH_PUNCTUATION |
p{Ps} | Character.START_PUNCTUATION |
p{Pe} | Character.END_PUNCTUATION |
p{Pc} | Character.CONNECTOR_PUNCTUATION |
p{Po} | Character.OTHER_PUNCTUATION |
p{Sm} | Character.MATH_SYMBOL |
p{Sc} | Character.CURRENCY_SYMBOL |
p{Sk} | Character.MODIFIER_SYMBOL |
p{So} | Character.OTHER_SYMBOL |
p{Pi} | Character.INITIAL_QUOTE_PUNCTUATION |
p{Pf} | Character.FINAL_QUOTE_PUNCTUATION |
p{all} | 所有字符 |
锚点及其他“零长度断言”
锚点及其他“零长度断言”都是用来匹配一个位置,而不是具体的字符。
起始位置:^、\A
脱字符(^)和\A会匹配输入文本的起始位置。但是如果启用了MULTILINE模式,^
还可以匹配每个行结束符之后的位置。
// \A会匹配起始位置 assertEquals( true , "abcde" .matches( "\\Aabcde" ));
// MULTILINE模式下,\A仍然只匹配起始位置,而不会匹配行结束符之后的位置! assertEquals( false , "\nabcde" .matches( "(?m)\n\\Aabcde" ));
// ^ 会匹配起始位置 assertEquals( true , "abcde" .matches( "^abcde" ));
// MULTILINE模式下,^会匹配行结束符之后的位置! assertEquals( true , "\nabcde" .matches( "(?m)\n^abcde" ));
// 甚至这样 assertEquals( true , "\na\nbcde" .matches( "(?m)\n^a\n^bcde" ));
|
结束位置:$、\Z和\z
$
比较复杂,它的含义依赖于MULTILINE模式是否启用。再次明确一下,行结束符会根据UNIX_LINES模式是否启用而变化。
-
未启用MULTILINE模式(默认)
$待匹配位置之后要么没有任意字符(即严格的结尾),要么只是行结束符,但需要要注意的是,在非UNIX_LINES模式下,它不能在\r\n之间。// 匹配严格的结尾
assertEquals(
true
,
"abcde"
.matches(
"abcde$"
));
// 匹配严格的结尾
assertEquals(
true
,
"abcde\r"
.matches(
"abcde\r$"
));
assertEquals(
true
,
"abcde\r\n"
.matches(
"abcde\r\n$"
));
// 匹配行结束符之前的位置
assertEquals(
true
,
"abcde\r"
.matches(
"abcde$\r"
));
assertEquals(
true
,
"abcde\n"
.matches(
"abcde$\n"
));
assertEquals(
true
,
"abcde\u0085"
.matches(
"abcde$\u0085"
));
assertEquals(
true
,
"abcde\u2028"
.matches(
"abcde$\u2028"
));
assertEquals(
true
,
"abcde\u2029"
.matches(
"abcde$\u2029"
));
assertEquals(
true
,
"abcde\r\n"
.matches(
"abcde$\r\n"
));
// 启用UNIX_LINES模式后,行结束符只有\n
assertEquals(
false
,
"abcde\r"
.matches(
"(?d)abcde$\r"
));
assertEquals(
true
,
"abcde\n"
.matches(
"(?d)abcde$\n"
));
assertEquals(
false
,
"abcde\u0085"
.matches(
"(?d)abcde$\u0085"
));
assertEquals(
false
,
"abcde\u2028"
.matches(
"(?d)abcde$\u2028"
));
assertEquals(
false
,
"abcde\u2029"
.matches(
"(?d)abcde$\u2029"
));
assertEquals(
false
,
"abcde\r\n"
.matches(
"(?d)abcde$\r\n"
));
// 启用UNIX_LINES模式后,$可以在\r\n之间
assertEquals(
true
,
"abcde\r\n"
.matches(
"(?d)abcde\r$\n"
));
// 还可以这样匹配
assertEquals(
true
,
"abcde\r\r\n"
.matches(
"abcde\r$\r\n"
));
assertEquals(
true
,
"abcde\n\r\n"
.matches(
"abcde\n$\r\n"
));
// 甚至是这样
assertEquals(
true
,
"abcde\r\n"
.matches(
"abcde$\r\n$"
));
assertEquals(
true
,
"abcde\r\n"
.matches(
"abcde$$\r\n$$"
));
// 但不能匹配
assertEquals(
false
,
"abcde\r\n"
.matches(
"abcde\r$\n"
));
// 不能匹配\r\n之间的位置
assertEquals(
false
,
"abcde\r\n\n"
.matches(
"abcde\r$\n\n"
));
// 不能匹配\r\n之间的位置
assertEquals(
false
,
"abcde\n\n"
.matches(
"abcde$\n$\n$"
));
// 第一个$不满足条件
-
启用MULTILINE模式
$能够匹配输入文本的严格末尾,或者行结束符之前的位置,需要注意的是,在非UNIX_LINES模式下,它同样不能在\r\n之间。// 非MULTILINE模式下的所有正则表达式,它都可以匹配成功。
// 但是从下面这个断言可以看出区别
assertEquals(
true
,
"abcde\n\n"
.matches(
"(?m)abcde$\n$\n$"
));
// 第一个$也满足条件
其实MULTILINE模式的启用只是允许$匹配文本中间的行(要不也不叫多行模式了)。
\Z等价于未启用MULTILINE模式的$。
// 与未启用MULTILINE模式的$一样 assertEquals( true , "abcde" .matches( "(?m)abcde\\Z" ));
assertEquals( true , "abcde\n" .matches( "(?m)abcde\\Z\n" ));
// 即使正则表达式启用了MULTILINE模式,也不能匹配成功 assertEquals( false , "abcde\n\n" .matches( "(?m)abcde\\Z\n\\Z\n\\Z" ));
|
\z则匹配输入文本的严格末尾,也即要求待匹配位置后面不能有任何字符(包括行结束符)。
// 匹配末尾 assertEquals( true , "abcde\n" .matches( "abcde\n\\z" ));
// 后面不能有任何字符,所以不能匹配 assertEquals( false , "abcde\n" .matches( "abcde\\z\n" ));
|
上次匹配成功的结束位置:\G
在迭代匹配中,有时候需要从上次匹配成功的结束位置继续匹配,就跟循环执行\A一样。
在每次成功匹配之后,Java会保存此次匹配的结束位置(见Matcher.last)。下次匹配时,如果上次起始位置与上次结束位置一样,则强制前进一个字符,防止无穷循环。如果要求匹配\G,则会比较当前的位置是否与上次结束位置相同,相同则匹配成功,否则匹配不成功。
1
|
assertEquals( "!a!b!c!d!e!" , "abcde" .replaceAll( "x?" , "!" ));
|
单词分界符:\b、\B
单词分界符\b用来匹配单词的边界,边界要求一边是单词字母,另一边不是单词字母。所谓单词字母,包括下划线(‘_’)、大小写字母、数字和非空格标记字符(Character.NON_SPACING_MARK),也即[\w\p{Mn}]。
\B则匹配不是单词边界的位置。
Java不区分左分界、右分界,而是笼统的边界。可以使用下面介绍的环视功能来区分左右边界,比如(?
顺序环视(?=…)、(?!…);逆序环视(?<=…)、(?<!…)
环视功能可以从当前位置向左或向右匹配执行的正则子表达式。向左查看称作逆序环视,向右查看称作顺序环视。
举例说明,对于字符串1234223432344234,(?<=2)234可以匹配到1234223432344234。
逆序环视要求长度是确定的,也即最大长度不能使无穷的。比如(?<=books?)是可以的,因为其最大长度是5,但(?<=\w+)是不行的。
注释和模式修饰符
模式修饰符:(?modifier),如(?i)和(?-i)
Java允许在正则表达式中使用模式修饰符来设定匹配模式,(?x)
开启x模式,(?-x)
关闭x模式。如果模式修饰符在括号内部,则其作用范围仅限于括号内部。
比如<B>(?i)text(?-i)</B>
,要求两边的TAG必须为大写,而启用的内容text则不关系大小写。<B>(?:(?i)text)</B>
也是相同的含义,因为(?i)只作用于括号内部。
// <B>(?i)text(?-i)</B> assertEquals( true , "<B>text</B>" .matches( "<B>(?i)text(?-i)</B>" ));
assertEquals( true , "<B>TEXT</B>" .matches( "<B>(?i)text(?-i)</B>" ));
assertEquals( false , "<b>text</B>" .matches( "<B>(?i)text(?-i)</B>" ));
// <B>(?:(?i)text)</B> assertEquals( true , "<B>text</B>" .matches( "<B>(?:(?i)text)</B>" ));
assertEquals( true , "<B>TEXT</B>" .matches( "<B>(?:(?i)text)</B>" ));
assertEquals( false , "<b>text</B>" .matches( "<B>(?:(?i)text)</B>" ));
|
i | 对应于Pattern.CASE_INSENSITIVE标志: 不区分大小写 |
d | 对应于Pattern.UNIX_LINES标志:只有\n 被视为行结束符,\r 等不再被视为行结束符 |
u | 对应于Pattern.UNICODE_CASE标志:当启用CASE_INSENSITIVE模式时,忽略大小写时会支持Unicode字符,而不仅仅是ASCII字符。具体地,此标志下,会使用Character.toUpperCase/toLowerCase来转换大小写。 |
x | 对应于Pattern.COMMENTS标志:忽略空白字符(即\s代表的字符),忽略#和行结束符之前的内容(同时也忽略行结束符)。 |
m | 对应于Pattern.MULTILINE标志:使得^和$可以匹配文本中间的行结束符之前和之后的位置。具体见^和$。 |
s | 对应于Pattern.DOTALL标志:点号. 可以匹配行结束符 |
局部模式修饰符:(?modifier:…),如(?i:…)
要限制模式修饰符的作用范围,除了将之放于括号内部,也可以简单地使用(?x:…)形式。比如<B>(?:(?i)text)</B>
可以简化成<B>(?i:text)</B>
。需要注意的是,虽然与括号形式类似,但它并不是捕获组,无法捕获内容。
文本范围: \Q…\E
\Q…\E会把其内部的字符当作普通文本来对待,而不是视为正则表达式。特别需要注意的是内部文本不能包含\E,可以使用\Q…\E\\E\Q…\E来代替。
1
2
3
4
|
// match: \s <--- \Q\s\E assertEquals( true , "\\s\\t" .matches( "\\Q\\s\\t\\E" ));
// match: \E <--- \Q\s\E\\E\Q\t\E assertEquals( true , "\\s\\E\\t" .matches( "\\Q\\s\\E\\\\E\\Q\\t\\E" ));
|
分组和捕获
捕获/分组括号:(…)和\1、\2、…
普通的没有特殊含义的括号通用用于分组和捕获,形式为(...)
。
对于捕获的分组,可以使用反向引用来获取子表达式匹配的文本。Java使用\1、\2、…形式的反向引用,后面的数字表示分组的编号。分组编号是按照左括号(
出现的次序来分配的。在Java中,分组编号的数目是没有限制的。
1
2
3
4
5
6
|
// 【样例1】捕获分组1:abc assertEquals( true , "abc1abc" .matches( "(\\w+)1\\1" ));
// 【样例2】捕获分组1:a,分组2:b,分组3:c assertEquals( true , "abc1cba" .matches( "(\\w)(\\w)(\\w)1\\3\\2\\1" ));
// 【样例3】一个很奇怪的例子,这与Java在匹配分组循环时回溯逻辑有关,具体原因不便讨论。 assertEquals( true , "abc11" .matches( "(\\w)+1\\1" ));
|
仅分组不捕获的括号:(?:…)
(?:…)仅用于分组,但不能用来提取文本。
固化分组:(?>…)
固化意思是说,一旦括号内的子表达式匹配成功之后,匹配的内容就被固化,在接下来的匹配过程中是不变的,除非整个子表达式被弃用。
1
2
3
|
assertEquals( true , "1abcde2" .matches( "1.*2" ));
// .*匹配到abcde2之后,将会被固化,但是之后的2无法匹配成功,需要强迫.*释放最后匹配的内容(即e),但是由于是固化分组,这个操作无法实现。 assertEquals( false , "1abcde2" .matches( "1(?>.*)2" ));
|
多选分支:…|…|…
多选分支可以用来在同一个位置测试多个子表达式。Java会按照从左到右的次序来匹配。子表达式可以为空表达式,比如(?:abc|)等价于(?:abc)?。
量词
匹配优先量词:*、+、?、{num,num}
两次可以限制作用对象的匹配次数。*
表示匹配次数零次或多次,+
表示匹配次数一次或多次,?
表示匹配次数零次或一次,{cmin,cmax}表示匹配次数为cmin到cmax次(均包含边界)。
需要注意,X{0,0}的意思不是“不出现X”,而是不进行任何匹配,也即跟没有是一样的。如果要实现“不出现X”,请使用否定环视功能。
忽略优先量词:*?、+?、??、{num,num}?
默认情况下,量词是匹配优先的,也即匹配尽可能多的内容。而忽略优先则相反,会匹配尽可能少的内容。
占有优先量词:*+、++、?+、{num,num}+
占有优先与固化分组类似,一旦匹配某些内容,将不会交还这些内容,除非整个子表达式被弃用。往往可以使用占有量词来优化正则表达式。
相关推荐
2. **正则表达式进阶** - **选择与或**:使用 `|` 符号实现多个模式的或操作,如 `abc|def` 可匹配 "abc" 或 "def"。 - **否定预查**:使用 `(?!...)` 表示后面不能跟指定的模式,如 `\d+(?!\d)` 匹配连续的数字但...
这个压缩包文件"正则表达式.rar"包含了一个名为"正则表达式.chm"的帮助文档,很可能是关于Java中正则表达式的详细教程或参考手册。 正则表达式的基本概念: 1. **模式(Pattern)**:正则表达式就是一种模式,它...
### Java正则表达式概述 #### 一、正则表达式简介 正则表达式是一种强大的文本处理工具,能够提供灵活而高效的模式匹配方法。它主要用于处理文本数据,包括查找特定字符模式、提取、编辑、替换或删除文本子字符串...
Java正则表达式是编程语言Java中用于处理文本的强大工具,它允许开发人员根据特定模式匹配、搜索和替换文本。在Java 2中引入的`java.util.regex`包提供了全面的支持,使得正则表达式的使用变得更为便捷。本文将探讨...
- **教程**:MDN Web文档、W3School等网站提供了详细的正则表达式教程。 5. **编程语言支持** - **Python**:使用`re`模块,提供了丰富的函数进行匹配、搜索、替换等操作。 - **JavaScript**:全局对象`RegExp`...
4. 正则表达式进阶: - **非贪婪匹配**:通过在量词后添加`?`,使匹配尽可能少的字符,如`.*?`。 - **否定预查**:`(?!)`表示后面不能跟指定的模式,如`a(?!b)`匹配不紧跟'b'的'a'。 - **条件表达式**:在某些...
10. **函数与方法**:在不同编程语言中,如JavaScript、Python、Java,使用正则表达式的方式略有不同,但通常都有`match`、`search`、`replace`、`split`等方法,用于执行查找、替换和拆分字符串的操作。 11. **...
还有各种教程和文档,如“正则表达式系统教程”、“Java正则表达式使用详解”等,可以帮助理解不同场景下的应用。 以上内容涵盖了JavaScript正则表达式的基础和进阶知识点,对于理解和使用JavaScript正则表达式进行...
四、正则表达式进阶 1. 分组与引用:`( )` 可以创建分组,`\1`、`\2` 等引用前面的分组。 2. 选择符:`|` 表示或关系,如 `/apple|banana/` 匹配 'apple' 或 'banana'。 3. 非贪婪匹配:在量词后加 `?` 可使匹配尽...
7. **正则表达式进阶** - **环视条件**: `(?=pattern)` 和 `(?!pattern)` 分别表示前瞻和后瞻,确保匹配前后满足特定条件。 - **非贪婪匹配**: 添加 `?` 使其变为非贪婪模式,例如 `.*?` 会尽可能少地匹配字符。 ...
2. **Java**:从Java 1.4开始引入java.util.regex包,支持正则表达式,Java 1.5和1.6增加了更多特性。 3. **PHP**:PHP在后来的版本中增加了内置的正则表达式支持,提供了preg_match系列函数。 4. **JavaScript**...
了解各种编程语言中的正则表达式API,结合实际需求编写高效、准确的正则表达式,是每个IT从业者必备的技能之一。通过学习和实践,你可以编写出更复杂、功能更强大的正则表达式,解决各种输入验证问题。
下面将详细讲解正则表达式的常见模式和使用方法,以及如何在Java和JavaScript中应用它们。 1. **基础概念** - **元字符**: 特殊含义的字符,如`.`代表任意字符,`^`表示行首,`$`表示行尾,`\`用于转义。 - **...
实例教程是学习正则表达式的好方法,因为它们可以帮助我们直观理解各种模式的工作原理。在实例教程中,你可以找到各种常见和复杂的正则表达式示例,如匹配邮箱地址、电话号码、日期格式等。通过实际操作,学习如何...
3. 正则表达式进阶: - 分组:使用括号可以将正则表达式分组,允许捕获和引用子匹配。 - 非捕获组:`(?:...)`可以创建一个非捕获组,不被当作独立的匹配项。 - 选择器:`(option1|option2)`表示option1或option2...
7. **Java API**:教程会介绍标准Java库中的一些关键类和接口,如日期时间API、正则表达式、网络编程(Socket和ServerSocket)、反射机制等。 通过学习这个Java2实用教程电子教程,读者不仅可以掌握Java编程的基本...
习题可能会涵盖字符串的创建、比较、截取、拼接以及使用正则表达式进行匹配和替换。 5. **异常处理**:学习如何使用try-catch-finally语句块来捕获和处理程序运行时可能出现的错误。 6. **集合框架**:Java集合...
此外,String类还支持其他方法,如split()用于分割字符串,matches()用于验证字符串是否匹配正则表达式,以及concat()用于连接两个字符串等。 在编程实践中,理解和熟练运用String类的各种方法可以提高代码的效率和...
这份笔记由多个部分组成,分别详细讲解了Java的基础语法、集合、多线程、IO以及反射和正则表达式等关键概念。 1. **基础语法**: - **变量与数据类型**:包括基本数据类型(如int、char、boolean)以及引用数据...