正则表达式语法详解
- 前言
- 一、基础概念
- 二、基础元字符
- 2.1 字符匹配
- 2.2 字符类
- 2.3 预定义字符类
- 三、重复匹配
- 3.1 贪婪与非贪婪匹配
- 3.2 精确重复匹配
- 四、边界匹配
- 4.1 行首与行尾匹配
- 4.2 单词边界匹配
- 五、分组与引用
- 5.1 分组
- 5.2 反向引用
- 5.3 命名分组
- 六、逻辑运算符
- 6.1 或运算
- 七、正则表达式在不同语言中的应用
- 7.1 Python 中的正则表达式
- 7.2 Java 中的正则表达式
- 7.3 JavaScript 中的正则表达式
- 总结
前言
在编程和文本处理领域,正则表达式是一种描述文本模式的强大工具。无论是验证用户输入、提取文本信息,还是替换特定字符串,正则表达式都能高效完成任务。掌握正则表达式的语法,能让开发者在处理文本数据时如虎添翼。本文我将从基础语法入手,逐步深入到进阶用法,结合丰富的代码示例,带你全面掌握正则表达式的核心语法。
一、基础概念
正则表达式(Regular Expression,简称 Regex 或 RE)是一种由字符和特殊符号组成的模式,用于匹配、查找和操作文本。它通过定义一系列规则,能够快速定位符合特定模式的字符串。在 Java、Python、JavaScript 等编程语言,以及文本编辑器(如 Sublime Text、VS Code)中,都广泛支持正则表达式。
二、基础元字符
2.1 字符匹配
普通字符:普通字符直接匹配自身。例如,正则表达式abc
会匹配字符串中出现的abc
子串。
import re
text = "abc123"
result = re.search("abc", text)
print(result.group()) # 输出:abc
转义字符:当需要匹配一些具有特殊含义的字符(如.
、*
、+
等)时,需要使用反斜杠\
进行转义。例如,正则表达式\.
匹配字符.
。
text = "example.com"
result = re.search("\.", text)
print(result.group()) # 输出:.
2.2 字符类
字符类用方括号[]
表示,用于匹配括号内的任意一个字符。
单个字符:[abc]
匹配a
、b
或c
中的任意一个字符。
text = "banana"
result = re.findall("[abc]", text)
print(result) # 输出:['a', 'a', 'a']
字符范围:[a-z]
匹配任意小写字母,[0-9]
匹配任意数字。
text = "abc123def"
result = re.findall("[0-9]", text)
print(result) # 输出:['1', '2', '3']
取反字符类:[^abc]
匹配除a
、b
、c
之外的任意字符。
text = "abcdef"
result = re.findall("[^abc]", text)
print(result) # 输出:['d', 'e', 'f']
2.3 预定义字符类
元字符 | 含义 | 示例 |
---|---|---|
. | 匹配除换行符\n 之外的任意字符 | a.c 匹配abc 、a0c 等 |
\d | 匹配任意数字,等价于[0-9] | \d+ 匹配连续的数字串 |
\D | 匹配任意非数字字符,等价于[^0-9] | \D+ 匹配连续的非数字字符 |
\s | 匹配空白字符(空格、制表符、换行符等),等价于[ \t\n\r\f\v] | \s+ 匹配连续的空白字符 |
\S | 匹配非空白字符,等价于[^ \t\n\r\f\v] | \S+ 匹配连续的非空白字符 |
\w | 匹配字母、数字或下划线,等价于[a-zA-Z0-9_] | \w+ 匹配连续的单词字符 |
\W | 匹配非字母、数字或下划线的字符,等价于[^a-zA-Z0-9_] | \W+ 匹配连续的非单词字符 |
text = "Hello 123 World!"
result1 = re.findall("\d", text)
result2 = re.findall("\s", text)
print(result1) # 输出:['1', '2', '3']
print(result2) # 输出:[' ', ' ']
三、重复匹配
3.1 贪婪与非贪婪匹配
*
:匹配前面的字符或字符类零次或多次(贪婪匹配,尽可能多地匹配)。例如,a*
匹配零个或多个a
。
text = "aaaaab"
result = re.search("a*b", text)
print(result.group()) # 输出:aaaaab
+
:匹配前面的字符或字符类一次或多次。例如,a+
至少匹配一个a
。
text = "aaaaab"
result = re.search("a+b", text)
print(result.group()) # 输出:aaaaab
?
:匹配前面的字符或字符类零次或一次。例如,a?b
匹配b
或ab
。
text1 = "b"
text2 = "ab"
result1 = re.search("a?b", text1)
result2 = re.search("a?b", text2)
print(result1.group()) # 输出:b
print(result2.group()) # 输出:ab
非贪婪匹配:在重复匹配符后加上?
,使其变为非贪婪模式,尽可能少地匹配。例如,<.*?>
(贪婪)与<.*?>
(非贪婪)在匹配 HTML 标签时的区别:
html = "<div>content1</div><div>content2</div>"
greedy_result = re.search("<.*>", html)
non_greedy_result = re.search("<.*?>", html)
print(greedy_result.group()) # 输出:<div>content1</div><div>content2</div>
print(non_greedy_result.group()) # 输出:<div>content1</div>
3.2 精确重复匹配
{n}
:匹配前面的字符或字符类恰好n
次。例如,a{3}
匹配连续的三个a
。
text = "aaab"
result = re.search("a{3}b", text)
print(result.group()) # 输出:aaab
{n,}
:匹配前面的字符或字符类至少n
次。例如,a{2,}
匹配至少两个连续的a
。
text = "aaaa"
result = re.search("a{2,}", text)
print(result.group()) # 输出:aaaa
{n,m}
:匹配前面的字符或字符类至少n
次,最多m
次。例如,a{1,3}
匹配一到三个连续的a
。
text1 = "a"
text2 = "aa"
text3 = "aaa"
result1 = re.search("a{1,3}", text1)
result2 = re.search("a{1,3}", text2)
result3 = re.search("a{1,3}", text3)
print(result1.group()) # 输出:a
print(result2.group()) # 输出:aa
print(result3.group()) # 输出:aaa
四、边界匹配
4.1 行首与行尾匹配
^
:匹配字符串的开头。例如,^abc
匹配以abc
开头的字符串。
text1 = "abcdef"
text2 = "defabc"
result1 = re.search("^abc", text1)
result2 = re.search("^abc", text2)
print(result1 is not None) # 输出:True
print(result2 is not None) # 输出:False
$
:匹配字符串的结尾。例如,abc$
匹配以abc
结尾的字符串。
text1 = "defabc"
text2 = "abcdef"
result1 = re.search("abc$", text1)
result2 = re.search("abc$", text2)
print(result1 is not None) # 输出:True
print(result2 is not None) # 输出:False
4.2 单词边界匹配
\b
:匹配单词边界(单词与非单词字符之间的位置)。例如,\bcat\b
只匹配独立的单词cat
,而不匹配category
中的cat
。
text1 = "cat is cute"
text2 = "category"
result1 = re.search("\bcat\b", text1)
result2 = re.search("\bcat\b", text2)
print(result1 is not None) # 输出:True
print(result2 is not None) # 输出:False
\B
:匹配非单词边界。例如,\Bcat\B
匹配category
中的cat
,但不匹配独立的cat
。
text1 = "cat is cute"
text2 = "category"
result1 = re.search("\Bcat\B", text1)
result2 = re.search("\Bcat\B", text2)
print(result1 is not None) # 输出:False
print(result2 is not None) # 输出:True
五、分组与引用
5.1 分组
使用圆括号()
进行分组,分组后的内容可以被后续引用或单独处理。例如,(abc)
将abc
作为一个分组。
text = "abcabc"
result = re.search("(abc)\\1", text)
print(result.group()) # 输出:abcabc
5.2 反向引用
反向引用使用\n
(n
为分组的编号,从 1 开始)来引用前面的分组。例如,(\d{3})-(\d{4})
可以通过\1
和\2
分别引用两个分组的内容。
text = "123-4567"
result = re.search("(\d{3})-(\d{4})", text)
print(result.group(1)) # 输出:123
print(result.group(2)) # 输出:4567
5.3 命名分组
在 Python 3.6 + 中,可以使用(?P<name>pattern)
进行命名分组,通过(?P=name)
进行反向引用。
text = "123-4567"
result = re.search("(?P<area_code>\d{3})-(?P<phone_num>\d{4})", text)
print(result.group("area_code")) # 输出:123
print(result.group("phone_num")) # 输出:4567
六、逻辑运算符
6.1 或运算
使用|
表示或运算,匹配|
两边的任意一个模式。例如,(cat|dog)
匹配cat
或dog
。
text1 = "I have a cat"
text2 = "I have a dog"
result1 = re.search("(cat|dog)", text1)
result2 = re.search("(cat|dog)", text2)
print(result1.group()) # 输出:cat
print(result2.group()) # 输出:dog
七、正则表达式在不同语言中的应用
7.1 Python 中的正则表达式
Python 通过re
模块支持正则表达式,常用方法包括re.search()
(查找第一个匹配项)、re.findall()
(查找所有匹配项)、re.sub()
(替换匹配项)等。
text = "hello 123 world 456"
new_text = re.sub("\d+", "xxx", text)
print(new_text) # 输出:hello xxx world xxx
7.2 Java 中的正则表达式
Java 通过java.util.regex
包支持正则表达式,使用Pattern
和Matcher
类进行操作。
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexExample {
public static void main(String[] args) {
String text = "hello 123 world 456";
Pattern pattern = Pattern.compile("\\d+");
Matcher matcher = pattern.matcher(text);
String newText = matcher.replaceAll("xxx");
System.out.println(newText); // 输出:hello xxx world xxx
}
}
7.3 JavaScript 中的正则表达式
JavaScript 通过RegExp
对象和字符串的相关方法(如match()
、replace()
)支持正则表达式。
let text = "hello 123 world 456";
let newText = text.replace(/\d+/g, "xxx");
console.log(newText); // 输出:hello xxx world xxx
总结
正则表达式的语法丰富且灵活,从基础的字符匹配到复杂的分组、反向引用和逻辑运算,每个部分都有其独特的用途。在实际应用中,需要根据具体需求选择合适的语法规则。通过不断练习和实践,才能熟练掌握正则表达式,在文本处理任务中发挥其强大的功能。
若这篇内容帮到你,动动手指支持下!关注不迷路,干货持续输出!
ヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノヾ(´∀ ˋ)ノ