如果有格式问题,请移步www.yuque.com/mrhuang-ire… 《正则表达式基础》 查看。
正则表达式使用单个字符串来描述、匹配一系列匹配某个语法规则的字符串,通常被用来检索、替换那些符合某个模式(规则)的文本。在开发中,经常会用到正则表达式,如电话号码邮件等校验、日志搜索以及文本替换。
基本书写符号
| **符号 ** | **符号解释 ** | **示例 ** | 解释 | 匹配输入 | |||
|---|---|---|---|---|---|---|---|
| \ | 转义符 | \* | 符号“*” | * | |||
| [ ] | 可接收的字符列表 | [efgh] | e、f、g、h中的任意1个字符 | e、f、g、h | |||
| [a-z0-9A-Z] | 任意单个小写字母、任意单个数字、任意单个大写字母 | a、b、0、9、A、Z | |||||
| [^] | 不接收的字符列表 | [^abc] | 除a、b、c之外的任意1个字符,包括数字和特殊符号 | m、q、5、* | |||
| 匹配“ | ”之前或之后的表达式 | ab | cd | ab或者cd | ab、cd | ||
| ( ) | 将子表达式分组 | (abc) | 将字符串abc作为一组 | abc | |||
| - | 连字符 | A-Z | 任意单个大写字母 | 大写字母 |
限定符
限定符包含匹配数量限制和位置限制。注意:* ,+,?等指定字符重复,字符可能是确切字符,也可能是一个范围内的字符,比如[0-9a-zA-Z]+,0ab是符合的,不是必须为000。
| **符号 ** | **符号解释 ** | **示例 ** | 解释 | 匹配输入 |
|---|---|---|---|---|
| * | 指定字符重复0次或n次 | (abc)* | 仅包含任意个abc的字符串,等效于\w* | abc、abcabcabc |
| + | 指定字符重复1次或n次 | m+(abc)* | 以至少1个m开头,后接任意个abc的字符串 | m、mabc、mabcabc |
| [0-9a-zA-Z]+ | 单个数字、大小写字母字符组成的字符串 | 0、12a、Zab | ||
| ? | 指定字符重复0次或1次 | m+abc? | 以至少1个m开头,后接ab或abc的字符串 | mab、mabc、mmmab、mmabc |
| {n} | 只能输入n个字符 | [abcd]{3} | 由abcd中字母组成的任意长度为3的字符串 | abc、dbc、adc |
| {n,} | 指定至少 n 个匹配 | [abcd]{3,} | 由abcd中字母组成的任意长度不小于3的字符串 | aab、dbc、aaabdc |
| {n,m} | 指定至少 n 个但不多于 m 个匹配 | [abcd]{3,5} | 由abcd中字母组成的任意长度不小于3,不大于5的字符串 | abc、abcd、aaaaa、bcdab |
| ^ | 指定起始字符 | ^[0-9]+[a-z]* | 以至少1个数字开头,后接任意个小写字母的字符串 | 123、6aa、555edf |
| $ | 指定结束字符 | ^[0-9]-[a-z]+$ | 以1个数字开头后接连字符“–”,并以至少1个小写字母结尾的字符串 | 0-aaa、0-a |
匹配字符集
| **符号 ** | **解释 ** | **示例 ** | **示例 ** | **匹配输入 ** | **不匹配输入 ** |
|---|---|---|---|---|---|
| . | 匹配除 \n 以外的任何字符 | a..b | 以a开头,b结尾,中间包括2个任意字符的长度为4的字符串 | aaab、aefb、a35b、a#*b | ab、aaaa、a347b |
| \d | 匹配单个数字字符,相当于[0-9] | \d{3}(\d)? | 包含3个或4个数字的字符串 | 123、9876 | 123、9876 |
| \D | 匹配单个非数字字符,相当于[^0-9] | \D(\d)* | 以单个非数字字符开头,后接任意个数字字符串 | a、A342 | aa、AA78、1234 |
| \w | 匹配单个数字、大小写字母字符,相当于[0-9a-zA-Z] | \d{3}\w{4} | 以3个数字字符开头的长度为7的数字字母字符串 | 234abcd、12345Pe | 58a、Ra46 |
| \W | 匹配单个非数字、大小写字母字符,相当于[^0-9a-zA-Z] | \W+\d{2} | 以至少1个非数字字母字符开头,2个数字字符结尾的字符串 | #29、#?@10 | 23、#?@100 |
分组构造
匹配子表达式内容,匹配结果以编号或显示命名的方式存在, 经常用来替换。
| 常用分组构造形式 | 说明 | 示例 | 解释 |
|---|---|---|---|
| () | 普通捕获组。捕获匹配的子字符串(或非捕获组)。编号为零的第一个捕获是由整个正则表达式模式匹配的文本,其它捕获结果则根据左括号的顺序从1开始自动编号。 | (\d{4})-((\d{2})-(\d{2}))输入字符串:"2017-04-25" | 有 4 个左括号,所以有 4 个分组:第0组 ,格式: (\d{4})-((\d{2})-(\d{2})), 匹配: 1990-10-14第1组,格式:(\d{4}),匹配:2017第2组,格式:((\d{2})-(\d{2})), 匹配:04-25第3组,格式:(\d{2}), 匹配:04第4组, 格式:(\d{2}), 匹配:25 |
| (?) | 命名捕获。将匹配的子字符串捕获到一个组名称或编号名称中。用于name的字符串不能包含任何标点符号,并且不能以数字开头。可以使用单引号替代尖括号,例如 (?'name') | (?\d{4})-(?(?\d{2})-(?\d{2}))输入字符串:"2017-04-25" | 第0组 ,名称:0, 格式: (\d{4})-((\d{2})-(\d{2})), 匹配: 1990-10-14第1组,名称:year, 格式:(\d{4}),匹配:2017第2组,名称:md, 格式:((\d{2})-(\d{2})), 匹配:04-25第3组,名称:month, 格式:(\d{2}), 匹配:04第4组, 名称:date, 格式:(\d{2}), 匹配:25 |
public class MatcherTest {
public static final String P_NAMED = "(?<year>\d{4})-(?<md>(?<month>\d{2})-(?<date>\d{2}))";
public static final String DATE_STRING = "2017-04-25";
public static void main(String[] args) throws Exception {
Pattern pattern = Pattern.compile(P_NAMED);
Matcher matcher = pattern.matcher(DATE_STRING);
matcher.find();
System.out.printf("\n===========使用名称获取=============");
System.out.printf("\nmatcher.group(0) value:%s", matcher.group(0));
System.out.printf("\n matcher.group('year') value:%s", matcher.group("year"));
System.out.printf("\nmatcher.group('md') value:%s", matcher.group("md"));
System.out.printf("\nmatcher.group('month') value:%s", matcher.group("month"));
System.out.printf("\nmatcher.group('date') value:%s", matcher.group("date"));
matcher.reset();
System.out.printf("\n===========使用编号获取=============");
matcher.find();
System.out.printf("\nmatcher.group(0) value:%s", matcher.group(0));
System.out.printf("\nmatcher.group(1) value:%s", matcher.group(1));
System.out.printf("\nmatcher.group(2) value:%s", matcher.group(2));
System.out.printf("\nmatcher.group(3) value:%s", matcher.group(3));
System.out.printf("\nmatcher.group(4) value:%s", matcher.group(4));
}
}
捕获组替换文本demo:
public class MatcherTest {
private static final Pattern TEMPLATE_ARG_PATTERN = Pattern.compile("\$\{(.+?)!}"); // ${param!}
private static final String TEMPLATE = "姓名:${dispatcher!},手机号:${phone!},年龄:${age!}";
public static void main(String[] args) throws Exception {
HashMap<String, String> ARGS = new HashMap<>();
ARGS.put("dispatcher", "张三");
ARGS.put("phone", "12345678901");
ARGS.put("age", "12");
Matcher m = TEMPLATE_ARG_PATTERN.matcher(TEMPLATE);
StringBuffer sb = new StringBuffer();
while (m.find()) {
String arg = m.group(1);
String replaceStr = ARGS.get(arg);
m.appendReplacement(sb, replaceStr != null ? replaceStr : "");
}
System.out.printf(sb.toString());
}
}
参考: