admin管理员组

文章数量:829196

正则表达式(regex,RE)

目录

1 语法规则

1.1 匹配一个字符(字母大写是取反)

1.2 自定义匹配一个字符([^regex]表示取反)

1,3 量词:规定前"一个"表达式出现的次数

1.4 零度断言

1.5 捕获组

1.5.1 数字捕获组

1.5.2 命名捕获组

1.5.3 非捕获组

1.5.4 捕获组的引用

1.6 修饰符

1.6.1 字母大小写

1.6.2 全局匹配

1.6.3 多行匹配

1.7 其它符号

1.7.1 分隔符

1.7.2 分组

1.7.3 定位符

1.7.4 特殊字符

2 使用环境

2.1 JAVA环境

2.2 JavaScript环境

3  用法示例


正则表达式是作用于字符串的一种校验语法,通过特定字符(0-9,A-Z,a-z等)组合而形成的一种具有校验功能的"校验字符串"

1 语法规则

1.1 匹配一个字符(字母大写是取反)

        \d匹配数字(0-9)

        \w匹配数字(0-9),字母(A-Z,a-z),下划线(_)

        \s空白符(空格,换行符,制表符)

        \n换行符

        .匹配任意一个字符(不包括换行符\n)    //常用[\s\S]表示所有字符

"2".matches("\\d"); //结果为true
"测".matches("\\D"); //结果为true"2".matches("\\w"); //结果为true
"A".matches("\\w"); //结果为true
"a".matches("\\w"); //结果为true
"_".matches("\\w"); //结果为true
"测".matches("\\W"); //结果为true" ".matches("\\s"); //结果为true"测".matches("."); //结果为true
"\n".matches("."); //结果为false"\n".matches("[\\s\\S]"); //结果为true

1.2 自定义匹配一个字符([^regex]表示取反)

        将自定义regex放在[ ]中,只要符合其中的一个字符即可

        -为连接符,[A-Z]表示A~Z中的一个

        匹配汉字采用unicode码    //匹配所有汉字[\u4e00-\u9fa5]

"f".matches("[a-z]");  //结果为true
"f".matches("[^a-z]");  //结果为false
"F".matches("[^a-z]");  //结果为true
"2".matches("[^a-z]");  //结果为true"正".matches("[\u6b63]");  //结果为true
"则".matches("[\u4e00\u9fa5]");  //结果为false
"表".matches("[\u4e00-\u9fa5]");  //结果为true

1,3 量词:规定前"一个"表达式出现的次数

        {n}匹配n次

        {m,}至少匹配m次

        {m,n}至少匹配m次,至多匹配n次

        ?匹配0次或1次,相当于{0,1}

        +至少匹配一次,相当于{1,}

        *匹配0次或任意次,相当于{0,}

"123".matches("\\d{3}");  //结果为true
"123".matches("\\d{2}");  //结果为false"123".matches("\\d{2,}");  //结果为true"123".matches("\\d{2,4}");  //结果为true"1".matches("\\d?");  //结果为true"12345".matches("\\d+");  //结果为true"12345".matches("\\d*");  //结果为true

        +和*匹配模式都是"贪婪模式(即尽可能多地匹配)"

        只要在它们后面加上一个?就可以变为"非贪婪模式(即尽可能少地匹配)"

                例: "<h1>一号字体</h1>"用"<.*>"匹配到1处"<h1>一号字体</h1>"

                     "<h1>一号字体</h1>"用"<.*?>"匹配到2处"<h1>一号字体</h1>"

1.4 零度断言

        先解释一下名词:"零度断言"分为"零度"和"断言"

                零度:就是指没有宽度,即向前或向后不占字符

                断言:指明在特定内容之前或之后并满足相应规则的内容,类比生活中常说的"我断定什么",例如"我断定他身后站着一个人"

        断言符号:①exp1(?=exp2)  匹配exp1,但同时exp1后面的内容要满足exp2

                        ②exp1(?!exp2)  匹配exp1,但同时exp1后面的内容不满足exp2

                        ③(?<=exp2)exp1  匹配exp1,但同时exp1前面的内容要满足exp2

                        ④(?<!exp2)exp1  匹配exp1,但同时exp1前面的内容不满足exp2

"1regex456apple789".split("[a-z]{5}(?=\\d{3})");  //返回数组[1, 456, 789]
"1regex56apple789".split("[a-z]{5}(?!\\d{3})");  //返回数组[1, 56apple789]
"1regex456apple789".split("(?<=\\d{3})[a-z]{5}");  //返回数组[1regex456, 789]
"1regex456apple789".split("(?<!\\d{3})[a-z]{5}");  //返回数组[1, 456apple789]

1.5 捕获组

        把被"子表达式"匹配到的数据保存在内存中,并按数字编号形成"数字捕获组"或按显式命名形成"命名捕获组",方便后面引用(正则表达式内部引用,正则表达式外部引用)

1.5.1 数字捕获组

        分组规则:从整个正则表达式从左往右找,(第n次出现即捕获组编号就是n,同时和与之对应的)以及两者包含的表达式共同形成n号捕获组,第0组则表示整个正则表达式

捕获组正则表达式匹配内容
0(\d{4})-(\d{2}-(\d\d))2022-08-21
1(\d{4})2022
2(\d{2}-(\d\d))08-21
3(\d\d)21
Pattern pattern = Pattern.compile("(\\d{4})-(\\d{2}-(\\d\\d))");
Matcher matcher = pattern.matcher("2022-08-21");
while (matcher.find()) {System.out.println(matcher.group(0));System.out.println(matcher.group(1));System.out.println(matcher.group(2));System.out.println(matcher.group(3));
}//2022-08-21
//2022
//08-21
//21

1.5.2 命名捕获组

        语法规则:(?<name>regex)

                例: (?<hour>(0[1-9]|1\d|2[0-3])):(?<minute>([0-5]\d)):(?<second>([0-5]\d))

捕获组正则表达式匹配内容
0

((0[1-9]|1\\d|2[0-3])):(([0-5]\\d)):(([0-5]\\d))

16:14:22
hour((0[1-9]|1\\d|2[0-3]))16
munite(([0-5]\\d))14
second(([0-5]\\d))22
Pattern pattern = Pattern.compile("(?<hour>(0[1-9]|1\\d|2[0-3])):(?<minute>([0-5]\\d)):(?<second>([0-5]\\d))");
Matcher matcher = pattern.matcher("16:14:22");
while (matcher.find()) {System.out.println(matcher.group(0));System.out.println(matcher.group("hour"));System.out.println(matcher.group("minute"));System.out.println(matcher.group("second"));
}//16:14:22
//16
//14
//22

1.5.3 非捕获组

        博主个人认为叫"失效捕获组"更为贴切,因为它会让原本的捕获组失效

        语法规则:(?:regex)

                例: (?:\d{4})-(\d{2}-(\d\d))

捕获组正则表达式匹配内容
0(\d{4})-(\d{2}-(\d\d))2022-08-21
1(\d{2}-(\d\d))08-21
2(\d\d)21
Pattern pattern = Pattern.compile("(?:\\d{4})-(\\d{2}-(\\d\\d))");
Matcher matcher = pattern.matcher("2022-08-21");
while (matcher.find()) {System.out.println(matcher.group(0));System.out.println(matcher.group(1));System.out.println(matcher.group(2));
}//2022-08-21
//08-21
//21

1.5.4 捕获组的引用

        捕获组引用的是捕获的"内容",即匹配结果,而不是子表达式本身

1.5.4(1) 外部引用

        通过Matcher对象的group(int)或group(name)方法可以获取对应的捕获组,并返回捕获组匹配后的数据

1.5.4(2) 内部引用

        在正则表达式内部进行的引用也可以叫做"反向引用"

        数字捕获组反向引用\n

        命名捕获组反向引用\k<name>或\k'name'

"33a55".matches("(\\d)\\1[a-z]+(\\d)\\1");  //返回false
"33a53".matches("(\\d)\\1[a-z]+(\\d)\\1");  //返回true//regex中两个\1指的都是编号为1的捕获组

        反向引用使用场景:

                例: 查找一串字母中成对出现的字母

Pattern pattern = Pattern.compile("([a-z])\\1");
Matcher matcher = pattern.matcher("aaabbcdlkkkkkjbcc");
while (matcher.find()) {System.out.println(matcher.group());
}//aa
//bb
//kk
//kk
//cc

                例: 号码中是否有6位连续相同的数字

Pattern pattern = Pattern.compile("(\\d)(?=\\1{5})");
Matcher matcher = pattern.matcher("25235235234");
System.out.println(matcher.find());  //不存在Pattern pattern = Pattern.compile("(\\d)(?=\\1{5})");
Matcher matcher = pattern.matcher("26666667891");
System.out.println(matcher.find());  //存在

1.5.4(3) 正则替换

        数字捕获组用$n指代,命名捕获组用${name}指代

"123abc456def789".replaceAll("(\\d+)([a-z]+)", "$1换");  //123换456换789"123abc456def789".replaceAll("(?<one>\\d+)(?<two>[a-z]+)", "${two}换");  //abc换def换789

1.6 修饰符

        JS环境的修饰符不写在正则表达式里,而写在表达式之外,指定额外的匹配策略

1.6.1 字母大小写

        JAVA环境: (?i)之后的表达式字母不区分大小写,(?i)不算捕获组

        JS环境: 表达式外添加i

"ABC".matches("(?i)abc");  //返回true
"aBC".matches("a(?i)bc");  //返回true
"abc".matches("a((?i)b)c");  //返回true

1.6.2 全局匹配

        JS环境: 表达式外添加g修饰符可以查找字符串中所有的匹配项,不加g则只查找第一次匹配项

'a1bk3u4f'.match(/\d/);  //返回["1"]
'a1bk3u4f'.match(/\d/g);  //返回["1","3","4"]

1.6.3 多行匹配

        JS环境: 表达式外添加m修饰符可以匹配多行

1.7 其它符号

1.7.1 分隔符

        符合|前的表达式或符合|后的表达式,通常将|前后的表达式约束在( )中

"D123".matches("[A-Z]\\d{3}|\\d{4}");  //"D123"或"1234"符合
"D1234".matches("[A-Z](\\d{3}|\\d{4})");  //"D123"或"D1234"符合

1.7.2 分组

        写在( )中的表达式称为子表达式,子表达式是一个整体(即一个分组),其后的量词是对这个整体起作用

"regexx".matches("regex{2}");  //结果为true
"regexregex".matches("(regex){2}");  //结果为true

1.7.3 定位符

        ^表示开头和$表示结尾,通常将^和$配合使用

                例: "<h1>一号字体</h1>"用"<.*?>"匹配到2处"<h1>一号字体</h1>"

                      "<h1>一号字体</h1>"用"^<.*?>$"匹配到1处"<h1>一号字体</h1>"

        \b表示单词边界,\B表示非单词边界

                例: "this is a island"用"is"匹配到3处"this is a island"

                      "this is a island"用"\bis"匹配到2处"this is a island"

                      "this is a island"用"is\b"匹配到2处"this is a island"

                      "this is a island"用"\bis\b"匹配到1处"this is a island"

1.7.4 特殊字符

        如果想匹配特殊字符($  (  )  *  +  .  [  ?  \  ^  {  |),需要在特殊字符前加上转义符\

                例: 想匹配?,因为?是特殊字符,因此要写成\?,而\在字符串中也代表转义符,因此写法应该是\\?

"?".matches("\?");  //写法错误
"?".matches("\\?");  //结果为true

                例: 同理,想匹配\,应该写成\\,如果正则参数写在字符串中,则应该写成\\\\

"\\".matches("\\");  //写法错误
"\\".matches("\\\\");  //结果为true

2 使用环境

2.1 JAVA环境

        str.matches(regex)   str完全匹配regex   本质是Pattern.matches(regex,str)

        str.replaceFirst(regex,str2)   将str中第一次满足regex的内容替换为str2   本质是Matcher.replaceFirst(replacement)

        str.replaceAll(regex)   将str中所有满足regex的内容替换为str2   本质是Matcher.replaceAll(replacement)

        str.split(regex)   以regex为分隔,返回String[ ]   //①如果原字符串为”空字符串”,返回的数组长度为1,数组第一个元素为”空字符串” ②如果字符串第一个字符满足regex分隔,那么返回的数组第一个元素是”空字符串”   本质是Pattern.compile(regex).split(str)

"23456f".matches("\\d+");  //返回false
"12ab33db56cf".replaceFirst("\\d+", "换");  //返回"换ab33db56cf"
"12ab33db56cf".replaceAll("\\d+", "换");  //返回"换ab换db换cf"
Arrays.toString("12ab33db56cf".split("\\d+"));  //返回[, ab, db, cf]

2.2 JavaScript环境

        创建正则表达式对象RegExp: 将正则写在/regex/中,修饰符写在/regex/外

var reg = /regex/gim;

        reg.test(str)   字符串中是否有符合正则的内容(有一个即可,无需完全匹配),返回boolean

var reg = /\d/;
reg.test('阿发123');  //返回true

        str.search(reg)   搜索字符串中第一次符合reg的位置(从0开始),没有返回-1

'abecbbf'.search(/BB/i);  //返回4

        str.match(reg)   搜索字符串中符合reg的内容,并以数组的形式返回,没有就返回null

'a1bk3u4f'.match(/\d/);  //返回["1"]
'a1bk3u4f'.match(/\d/g);  //返回["1","3","4"]

        str.replace(reg,str2)   查找str中符合reg的内容,并用str2替换

'我是湖北的,湖北汉族人'.replace(/湖北/,'中国');  //返回"我是中国的,湖北汉族人"
'我是湖北的,湖北汉族人'.replace(/湖北/g,'中国');  //返回"我是中国的,中国汉族人"

        str.split(reg)   以str中符合reg的内容为分割,返回数组

'1ab23df65sf23'.split(/\d+/);  //返回[ "", "ab", "df", "sf", "" ]

        str.trim()   去掉str首尾空格

3  用法示例

账户金额    ^\d{1,3}(,\d{3})*.\d{2}$    例:5,231,247.08

电话号码    ^(13[0-9]|14[01456789]|15[012356789]|16[0256789]|17[0-9]|18[0-9]|19[012356789])\d{8}$    例:15176767856

本文标签: 正则表达式(regexRE)