匹配URL地址
匹配目多级子目录以及可选的args
匹配目标地址或者主机名以及可选的port
匹配协议名以及可选的username:password
虽然Java不支持嵌入条件,但想要匹配美国邮政编码的话可以使用\b\d{5}(-\d{4})?(?!-)\b
Java的RegEx不支持嵌入条件也不支持POSIX元字符类
正则表达式 想匹配出需要的内容很容易实现,但是要求其不能匹配出我们不需要的内容(即精确匹配)却很困难
精确匹配邮箱地址
除了正前后查找还有,负前后查找,他们的操作符分别是
(?!)
和 (?<!)
规则类似
在Ea
和Eb
表达式,前者匹配长度可以是任意的
后者则必须是固定的,不能出现诸如*
+
{2,}
类似的表达式
否则如果使用的是Java RegEx
的话,将抛出
Exception in thread "main" java.util.regex.PatternSyntaxException: Look-behind group does not have an obvious maximum length near index XX
但如果如果是集合或者单个字符,却可以配合使用如
(?<=[a-z]*)
(?<=\d*)
(?<=\w+)
(?<=f*)
但这些是非法的
(?<=a\w*)
(?<=k\d*)
(?<=\w\w+)
(?<=aa+)
换句话说,如果(positive lookahead)
要匹配不固定长,那么只能是单个集合
(?<=[afgvds]{2,})
这也是一个合法的向后查找
(?=Ea)
为向前查找,在一个表达式的尾部
(?<=Eb)
为向后查找,在一个表达式的尾部
Java
即支持正向前查找(positive lookahead)
,也支持正向后查找(positive lookbehind)
,他们是对某一位置的前后进行查找,但它们并不是匹配结果的一部分。
Java RegEx
不支持\U
\u
\L
\l
\E
这样的元字符
但是Intellj IDEA
支持
还原操作
RegEx | Replace |
---|---|
\((\d{3})\) (\d{3}-\d{4}) |
$1-$2 |
替换操作
RegEx | Replace |
---|---|
(\d{3})-(\d{3})(-)(\d{4}) |
($1) $2-$4 |
(\d{3})-(\d{3}-)(\d{4}) |
($1) $2$3 (而不是 ($1) $2-$3 必须要跨度大于1时,- 才被转义) |
(\d{3})-(\d{3}-\d{4}) |
($1) $2 |
(?<header>\d{3})-(?<tail>\d{3}-\d{4}) |
(${header}) ${tail} |
替换前 | 替换后 |
---|---|
494-939-5505 | (494) 939-5505 |
427-836-2491 | (427) 836-2491 |
142-620-0294 | (142) 620-0294 |
246-767-4276 | (246) 767-4276 |
585-328-1029 | (585) 328-1029 |
子表达式可用来进行回溯引用匹配,用
\1,\2,...\n
来分别代表第n个表达式
但如果子表达式的相对位置发生了变化,整个模式也许就不能再完成原来的工作,删除或添加子表达式的后果可能更为严重。
所以,一些比较新的正则表达式实现还支持命名捕获
:给某个子表达式起一个唯一的名字,然后用这个名字(而不是相对位置)来引用这个子表达式.
Java RegEx 支持命名捕获,可混合使用编号和命名来引用前面子表达式的内容
public static void main(String[] args) {
String input = "<BODY>\n" +
"<H1>Welcome to my Homepage</H1>\n" +
"Content is divided into two sections:<BR>\n" +
"<H2>ColdFusion</H2> <h2>ColdFusion</h2> <H3>Wireless</H5>\n" +
"Information about Macromedia ColdFusion.\n" +
"<H3>Wireless</H3>\n" +
"<H3>Wireless</h3>\n" +
"Information about Bluetooth, 802.11, and more.\n" +
"</BODY>";//<(?<x>[Hh])(?<y>[1-6]).*?\1\k<y>>
Pattern pattern = Pattern.compile("<(?<x>[Hh])(?<y>[1-6]).*?\\1\\k<y>>");
Matcher matcher = pattern.matcher(input);
System.out.println(pattern.pattern());
while (matcher.find()) {
System.out.println(matcher.group(0));//等价matcher.group()
System.out.println(matcher.group(1));//回溯引用第一个子表达式匹配到的内容
System.out.println(matcher.group(2));//回溯引用第二个子表达式匹配到的内容
System.out.println(matcher.group("x"));//采用命名捕获,回溯引用第一个子表达式匹配到的内容
System.out.println(matcher.group("y"));//采用命名捕获,回溯引用第二个子表达式匹配到的内容
}
System.out.println(matcher.toMatchResult().groupCount());//返回子表达式的个数
}
匹配1个字节能表达的范围0-255,使用
正则表达式\b(2[0-4]\d|25[0-5]|1?\d{1,2})\b
而不是\b(1?\d{1,2}|2[0-4]\d|25[0-5])\b
假如使用(1?\d{1,2}|2[0-4]\d|25[0-5])
匹配255时候,将匹配25
和5
而使用(1?\d{1,2}|2[0-4]\d|25[0-5])\.
匹配255.时候,将匹配255.
而不是55.
但要匹配55.
,则使用\B(1?\d{1,2}|2[0-4]\d|25[0-5])\.
如果使用了(?m)
的多行模式匹配,那么^
将匹配\n
的结束位置,
$
将匹配\n
的开始位置
Intellij IDEA
默认使用多行模式匹配
Java RegEx
支持使用?(m)
进行多行模式匹配
[\s\S]
将匹配任意字符类似的都具有该功能如[\w\W]
,[\d\D]
(.|\n)
也可以真正的匹配任意字符
input = " a\n" +
" /** this is a test \n" +
"code \n" +
"wo fas ga hdh sha\n" +
"end?\n" +
"*/*/\n" +
"*/";//(?m)^\s*/\*[\S\s]*?\*/
Pattern pattern = Pattern.compile("(?m)^\\s*/\\*[\\S\\s]*?\\*/");
Matcher matcher = pattern.matcher(input);
while (matcher.find())
System.out.println("[" + matcher.start() + ",\n"
+ matcher.group()
+ "\n," + matcher.end() + "]");
输出结果:
[3,
/** this is a test
code
wo fas ga hdh sha
end?
*/
,55]
^.*$可以匹配任意的非空字符串
\<
和\>
也用来匹配单词边界,前者匹配单词开头,后者匹配单词结尾,
但是Java
提供的正则表达式和Intellij IDEA
都不支持,egrep
程序支持
位置匹配元字符 | 功能描述 |
---|---|
\b | 不匹配任何字符,匹配\w与\W之间的位置 |
\B | 不匹配任何字符,匹配\w与\w或\W与\W之间的位置 |
匹配连线符
string | regex |
---|---|
nine-digit | \b-\b |
nine- digit | \b-\B |
nine - digit | \B-\B |
nine -digit | \B-\b |
\b
匹配且只匹配一个位置,不匹配任何字符。用\bcat\b
匹配到的字符串的长度是3个字符(c,a,t)
,不是5个字符。
贪婪型元字符 | 懒惰型元字符 |
---|---|
* | *? |
+ | +? |
{m,} | {m,}? |
{m,n} | {m,n}? |
对于下面的那种情况,使用<[Bb]>.{1,16}</[Bb]>
也会导致过度匹配.
M{X(,Y)} ,Y
是可选的
且0=<X<=Y
表示前面的M模式
将出现至少X
次,至多Y
次
?
是一个元字符,如果要匹配?本身,就必须使用它的转义序列\?
该元字符的功能是匹配0个或1个字符
\*
是一个元字符,如果要匹配*本身,就必须使用它的转义序列\\*
该元字符的功能是匹配0个或多个字符
[\r]?\n
用来兼容在window和linux/unix上的换行符兼容
+
是一个元字符,如果要匹配+本身,就必须使用它的转义序列\+
该元字符的功能是匹配一个或多个字符(或字符集合),但至少匹配一个
Java 和 Intellij IDEA 都不支持POSIX字符类`
可以使用16进制或者是8进制来表达正则表达式,但是用这种方式表达出的字符都是普通字符,
如[\060\x2d\071]可以翻译为[0-9]但是这个集合只包含0 - 9三个字符,等价于[0\-9]
正则表达式大小写敏感,而且通常对元字符来说大写是小写的取非,如
\w \W 前者等价 [a-zA-Z0-9_],w是 word 的意思,类似还有很多如
\d \D 前者等价 [0-9],d是 digit 的意思
input = "1-8-5-189";//[0-5-9] 匹配不到8,正则表达式采用的贪心的方式0-5集合- 和9 组成的集合
Pattern pattern = Pattern.compile("[0-5-9]");
Matcher matcher = pattern.matcher(input);
var myArray = new Array();
...
if (myArray[0] == 0) {
...
}
if (myArray[1] == 0) {
...
}
if (myArray[2] == 0) {
...
}
if (myArray[3] == 0) {
...
}
matches here using regex:
if (myArray[[0-9]] == 0) {\n...\n}
任何的一个元字符如果想要匹配其本身,都可以通过加上一个反斜杠做为其前缀的办法。
.和[类原始就是元字符, t和n类必须转义后才算是元字符
package regex;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* Created by E on 2017/8/1.
*/
@SuppressWarnings("UnusedAssignment")
public class _01 {
//以下测试的正则表达式都适用于java语言中的字符串表达的正则表达式
public static void main(String[] args) {
String input;
input = " car scar CAR Car CaR carry incarerate car carcar";//[Cc][Aa][Rr] 匹配所有car忽略大小写
input = "Hello, my name is Ben. Please visit my website at http://www.forta.com/.ben";//纯文本匹配
String s = "sales1.xls " +
"orders3.xls" +
" sales2.xls" +
" sales3.xls" +
" apac1.xls" +
" europe2.xls" +
" na1.xls" +
" na2.xls" +
" sa1.xls ";//.a.\\. 对于后面的\\对应一个java转义为一个反斜杠,然后\.告诉正则表达式这不是一个模式,纯文本
input = s;
input = "\\ 123.";//\\\\ java转义为两个\\,正则表达式转义成1个杠,然后匹配 字符串里面的一个杠杠\
input = "a\n";//a.无法匹配失败 .匹配任意字符除\n,\转义
input = "a\n";//a\\n \n匹配换行
input = s + " usal.xls";//[ns]a.\.xls 元字符使用
input = "The phrase \"regular expression\" is often\n" +
"abbreviated as RegEx or regex";//[Rr]eg[Ee]x
input = "sa2.java sa3.java sa6.java sa4.java sal.java ana3.java";//[ns]a[2-4].ja
input = "aaaaaaa";//aaa 只会匹配出2个,不会重叠匹配
input = "[a\\";//\\[a\\ , [Z-a]a[Z-a]
input = "<BODY BGCOLOR=\"#33A6b3\" TEXT=\"#FFfFFF\" MARGINWIDTH=\"0\" MARGINHEIGHT=\"0\" TOPMARGIN=\"0\" LEFTMARGIN=\"0\">";//#[0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f][0-9A-Fa-f]
input = "a2 b3 n4 zu qe su nd n8 68 4a t6";//[a-z][^2-4 86] X-Y,X和Y仅指单个字符对于后面的字符X都将属于这个集合
//[.]与\.等价,不然如[.af]没有意义af已经被包括在.所描述的集合范围内了,所以将失去他的原本功能
Pattern pattern = Pattern.compile("");
Matcher matcher = pattern.matcher(input);
int count = 0;
while (matcher.find()) {//输出
System.out.println("[" + matcher.start() + "," + matcher.group() + "," + matcher.end() + "]");
count++;
}
System.out.println(count);
}
}