介绍:
正则表达式(Regular Expressions,简称Regex或Regexp)是一种强大的文本处理工具,它使用一种特殊的语法来匹配字符串中的字符组合。它们广泛用于各种编程语言和文本处理工具中,以执行各种文本搜索、替换、验证和数据提取等操作。以下是一些正则表达式可以用来完成的主要工作:
- 数据验证:
- 验证电子邮件地址、电话号码、身份证号码、URL、信用卡号等格式的正确性。
- 验证用户输入的数据是否符合特定的格式要求。
- 搜索和查找:
- 在大量文本中搜索符合特定模式的字符串。
- 查找特定格式的日期、时间或数字序列。
- 文本替换:
- 将文本中的某些模式替换为其他文本。例如,将日期格式从MM/DD/YYYY更改为YYYY-MM-DD。
- 去除或替换HTML标签、特殊字符等。
- 分割字符串:
- 使用正则表达式定义的分隔符来分割字符串,这比使用简单的空格或逗号作为分隔符更为灵活和强大。
- 数据提取:
- 从文本中提取符合特定模式的信息,如电子邮件地址、URL、电话号码等。
- 从日志文件、HTML页面或其他复杂文本格式中提取有用信息。
- 路由和URL映射:
- 在Web开发中,使用正则表达式来定义URL的路由规则,以便根据请求的URL执行相应的操作。
- 文件重命名和批量处理:
- 批量重命名文件,基于文件名中的特定模式。
- 在批量处理文本文件时,对文件中的数据进行格式化或转换。
- 编写词法分析器:
- 在编译器和解释器的开发中,正则表达式用于定义词法单元(如关键字、标识符、操作符等)的语法规则。
- 数据清洗:
- 在数据预处理阶段,使用正则表达式来清洗数据,如去除空白字符、修正拼写错误、统一数据格式等。
- 安全防护:
- 在网络安全领域,正则表达式用于检测潜在的恶意输入,如SQL注入、跨站脚本(XSS)攻击等。
摘自文心一言
我的理解:正则表达式主要是对字符串进行操作。regular这个单词有规则的意思,那么正则表达式可以理解为程序员按照一定的语法格式定义的一段个性化的规则,可以用这种规则去对字符串进行筛选、验证等等操作。
基本语法
正则表达式的基本语法由普通字符(即文本字符)和元字符(特殊字符)组成。例如,正则表达式 hello
就是由普通字符 h
、e
、l
、l
、o
组成的。
基本组成
- 普通字符:正则表达式中的普通字符(如字母a到z、A到Z、数字0到9等)会按照字面意义进行匹配。
- 元字符:正则表达式中的特殊字符,用于表示字符集合、位置信息、重复次数等,如
.
、*
、+
、?
、^
、$
、[ ]
、{ }
、|
、\
等。
1、如果一个正则表达式只由普通字符组成,它的逻辑其实是匹配。比如说我定义了一个正则表达式regex="abc";就代表除了字符串"abc",其他的字符串均不匹配。不管是"ab"、"bac"均返回false;
字符串中的正则表达式方法是public boolean matchs(String regex)
2、元字符的作用:有了元字符,就可以自定义一些规则
常用元字符
.
:匹配除换行符\n
之外的任意单个字符。*
:匹配前面的子表达式零次或多次。+
:匹配前面的子表达式一次或多次。?
:匹配前面的子表达式零次或一次。^
:匹配输入字符串的开始位置,如果设置了多行标志(m
),则也可以匹配行首。$
:匹配输入字符串的结束位置,如果设置了多行标志(m
),则也可以匹配行尾。[ ]
:字符集合,匹配方括号中的任意一个字符。例如[abc]
匹配a
、b
或c
。一次只能匹配一个字符,多了不行。可以进行嵌套,例如[a-m[o-s]]表示a-s或o-s,同理,&&一样有与门的作用。[^ ]
:否定字符集合,匹配不在方括号中的任意一个字符。例如[^abc]
匹配除了a
、b
、c
之外的任意字符。{n}
:n
是一个非负整数,匹配前面的子表达式恰好n
次。{n,}
:n
是一个非负整数,匹配前面的子表达式至少n
次。{n,m}
:n
和m
都是非负整数,其中n<=m
,匹配前面的子表达式至少n
次,但不超过m
次。- 注意:^和$不能乱用,这两个符号用了就表示你只能匹配字符串开头或结尾处符合规则的子串,文本中间的就匹配不到了。
下面的元字符前面的反斜杠其实都是转义字符,它的作用是让计算机不把它们看作普通字符,而是看作元字符。同理,反斜杠本身也有作为字符的含义,所以需要再加上一个反斜杠将其变为元字符反斜杠,通俗来说,就是两个反斜杠 \\ 等于一个反斜杠 \
那为什么实际使用中需要打出\\d才能被计算机识别呢?
在实际编程中,当你需要在字符串中嵌入正则表达式(包括像
\d
这样的转义序列)时,你通常需要使用两个反斜杠\\
而不是一个,这是因为字符串本身也会对反斜杠进行转义处理。字符串字面量中的反斜杠(
\
)是一个特殊的转义字符,用于引入诸如换行符(\n
)、制表符(\t
)等特殊字符,或者用于在字符串中表示那些不能直接在字符串中使用的字符(比如双引号本身,在双引号界定的字符串中需要使用\"
来表示)。因此,当你想要在字符串中表示一个字面的反斜杠时,你需要使用两个反斜杠(\\
)来“转义”这个反斜杠字符,从而使其被解释为字符串中的一个普通字符。然而,在正则表达式中,反斜杠同样被用作转义字符,用于引入特殊字符或字符类(如
\d
、\w
、\s
等)。因此,当你在字符串中嵌入一个正则表达式时,你需要对正则表达式中的反斜杠进行双重转义:第一次是为了在字符串中表示一个字面的反斜杠,第二次是为了在正则表达式中表示一个具有特殊含义的转义序列。简单来说,字符串和正则表达式是两种体系,但是正则表达式同样是以字符串的形式呈现的,因此,反斜杠\就需要进行双重转义 \\ 中,第一个反斜杠将第二个反斜杠转义成了普通的反斜杠,但是在正则表达式中,普通的反斜杠恰恰也有转义效果,因此使用双重反斜杠才能被正则表达式识别。 \w
:匹配字母、数字、下划线,等同于[a-zA-Z0-9_]
。\W
:匹配任意非单词字符,等同于[^a-zA-Z0-9_]
。\s
:匹配任意空白字符,包括空格、制表符、换行符等。\S
:匹配任意非空白字符。\d
:匹配任意数字,等同于[0-9]
。\D
:匹配任意非数字字符,等同于[^0-9]
。\b
:匹配单词边界,即单词字符和非单词字符之间的位置。\B
:匹配非单词边界。
转义字符
在正则表达式中,一些字符具有特殊意义,如果希望匹配这些字符本身,需要使用反斜杠\
进行转义。例如,要匹配点(.
)字符,需要使用\.
来表示。
4. 分组和引用
()
:捕获组,用于将匹配到的字符串保存在一个临时变量中,以便后续使用。
捕获组有组号,从左往右第一个捕获组组为为1,以此类推。
正则表达式内部使用:\\+组号 外部使用:$+组号
- 非捕获组:
非捕获组(Non-capturing Group)是正则表达式中的一个概念,用于将一组字符视为一个整体进行匹配,但与捕获组(Capturing Group)不同的是,非捕获组在匹配过程中不会捕获匹配的文本供后续引用或处理。捕获组通过圆括号
()
包围,并且匹配的文本可以通过特定的引用方式(如反向引用、分组引用等)在正则表达式或后续处理中被访问。非捕获组通过在圆括号内使用
?:
开头来定义,即(?:...)
。这样做的好处是可以将一组字符视为一个整体进行匹配,而不需要在匹配结果中保留这部分文本的副本,从而节省了内存和可能的处理时间。非捕获分组不占用组号。使用场景
非捕获组通常用于以下几种情况:
-
提高性能:当你知道某个分组在后续处理中不会被引用时,使用非捕获组可以减少正则表达式引擎的工作量,因为它不需要为这部分文本分配额外的存储空间。
-
逻辑组合:有时你需要将一组字符视为一个整体进行匹配,但这部分文本本身并不需要被单独提取或引用。例如,在匹配电话号码时,你可能需要确保电话号码由三个数字区号、一个连字符和七个数字组成,但你并不关心区号或后续数字的具体值,只是需要验证整个格式。
-
与量词结合使用:非捕获组经常与量词(如
*
、+
、?
、{n}
等)结合使用,以匹配某个模式出现零次或多次的情况,但又不希望捕获这些匹配项。 \n
:在匹配模式中,\n
表示引用第n
个捕获组的内容。
5. 修饰符(修正符)
在不同的编程语言中,正则表达式可能支持不同的修饰符,用于对匹配过程进行额外的控制。例如,在JavaScript中,修饰符i
表示不区分大小写,在Java中应该这样写:(?i),g
表示全局匹配,m
表示多行匹配。
6. 示例
- 匹配电子邮件地址:
^\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*$
- 匹配URL:
^(https?|ftp)://[^\s/$.?#].[^\s]*$
- 匹配中国大陆手机号码:
^1[3456789]\d{9}$
7.断言
在正则表达式中,断言(Assertions)是一种特殊类型的模式,用于指定某个位置应该符合一定的条件,但不消耗(即不移动匹配指针)任何字符。断言本身不会匹配任何字符,它只是用来测试字符串在某个位置是否能满足特定的条件。根据断言的性质,可以分为前瞻断言(Lookahead)和后顾断言(Lookbehind),以及它们的否定形式。
前瞻断言
- 正向前瞻断言(Positive Lookahead):
(?=...)
- 断言此位置后面能匹配表达式
...
。例如,java(?=\d+)
会匹配"java",但这"java"后面必须跟着至少一个数字。
- 断言此位置后面能匹配表达式
- 负向前瞻断言(Negative Lookahead):
(?!...)
- 断言此位置后面不能匹配表达式
...
。例如,java(?!\d+)
会匹配"java",但这"java"后面不能跟着数字。
- 断言此位置后面不能匹配表达式
后顾断言
后顾断言在一些正则表达式引擎中是支持的,但在某些引擎(如JavaScript的RegExp
)中可能不受支持。可以使用正向后顾断言匹配紧跟在"java"后面的数字
- 正向后顾断言(Positive Lookbehind):
(?<=...)
- 断言此位置前面能匹配表达式
...
。注意,并不是所有的正则表达式引擎都支持后顾断言。例如,(?<=java)\d+
会匹配紧跟在"java"后面的一个或多个数字。
- 断言此位置前面能匹配表达式
- 负向后顾断言(Negative Lookbehind):
(?<!...)
- 断言此位置前面不能匹配表达式
...
。同样,后顾断言的支持取决于正则表达式引擎。例如,(?<!java)\d+
会匹配不是紧跟在"java"后面的一个或多个数字。
- 断言此位置前面不能匹配表达式
注意事项
- 断言本身不消耗(即不移动匹配指针)任何字符,它们只是用来检查某个位置是否符合特定的条件。
- 并不是所有的正则表达式引擎都支持后顾断言。
- 在使用断言时,需要注意正则表达式引擎的特定语法和限制。
字符串中用到正则表达式的方法
在String类的成员方法中,只要参数有String regex,该方法就用到了正则表达式。
常用方法:
1、public boolean matches(String regex) 判断字符串是否符合传入的正则表达式的要求
这个方法中,正则表达式会默认从字符串的开头校验的结尾,字符串必须是严格从头到尾符合正则表达式。
2、 public String replaceAll(String regex,String newstr) 按照正则表达式的规则进行替换
这个方法会找到字符串中符合于正则表达式匹配的子串,并替换为newstr。该方法在内部其实也是创建了Pattern和Matcher的实例,并调用了Matcher类中的replaceAll方法进行替换。
3、public String[ ] split(String regex) 按照正则表达式规则切割字符串
这个方法以符合正则表达的部分作为分隔符,把字符串分割成多个部分,返回字符串数组。