- 正则表达式(Regular Expression),在编程语言中通常缩写为regex或regexp,是一种用于字符串搜索和操作的模式描述方法。它通过定义一系列的规则来匹配、查找和管理文本数据。
正则表达式在线校验: https://tool.oschina.net/regex/
正则表达式在各种编程任务中都有广泛的应用。以下是一些常见的用途:
在介绍正则表达式之前,我们需要了解一些基本的组成元素:
.
匹配除换行符之外的任意单个字符。\d
等同于 [0-9]
,匹配任意一个数字字符。\D
等同于 [^0-9]
,匹配任意一个非数字字符。[a-z]
匹配任意一个英文小写字母。[^a-z]
匹配任意一个非英文小写字母的字符。*
:出现0次或多次。+
:出现1次或多次。?
:出现0次或1次。{n}
:确定出现n次。{n,}
:至少出现n次。{n,m}
:出现n到m次。^
:行的开头。$
:行的结尾。\b
:单词边界。\B
:非单词边界。[]
:定义一个字符集,匹配其中的任意单个字符。[^]
:取反,匹配不在字符集中的任意单个字符。字符类用于定义一组可以匹配的字符。它们通过方括号[]
来表示,在匹配过程中,只要目标字符属于字符类中定义的范围,就会成功匹配。
[abc]
:匹配a
、b
或c
中的任意一个字符。例如,正则表达式[abc]
可以匹配字符串cat
中的c
。
[^abc]
:匹配除a
、b
或c
之外的任意字符。例如,正则表达式[^abc]
可以匹配字符串dog
中的d
。
[a-z]
:匹配所有小写字母(从a
到z
)。例如,正则表达式[a-z]
可以匹配字符串hello
中的h
。
[A-Z]
:匹配所有大写字母(从A
到Z
)。例如,正则表达式[A-Z]
可以匹配字符串Hello
中的H
。
[0-9]
:匹配所有数字字符(从0
到9
)。例如,正则表达式[0-9]
可以匹配字符串year2024
中的2
。
[a-zA-Z0-9]
:匹配所有字母和数字,即大小写字母和数字组合。例如,正则表达式[a-zA-Z0-9]
可以匹配字符串Pass123
中的P
、a
、s
等字符。
在正则表达式中,为了方便书写和理解,常用字符类通常会有一些简写形式:
\d
:匹配任意一个数字字符,等同于[0-9]
。
\D
:匹配任意一个非数字字符,等同于[^0-9]
。
\w
:匹配任意一个字母、数字或下划线字符,等同于[a-zA-Z0-9_]
。
\W
:匹配任意一个非字母、非数字和非下划线字符,等同于[^a-zA-Z0-9_]
。
\s
:匹配任意一个空白字符,包括空格、制表符、换行符等,等同于[ \t\n\r\f\v]
。
\S
:匹配任意一个非空白字符,等同于[^ \t\n\r\f\v]
。
在一些编程语言和工具中,还支持POSIX字符类,它们是预定义的一些字符类,用于匹配特定类型的字符。
[:alnum:]
:匹配所有字母和数字字符,等同于[a-zA-Z0-9]
。
[:alpha:]
:匹配所有字母字符,等同于[a-zA-Z]
。
[:digit:]
:匹配所有数字字符,等同于[0-9]
。
[:lower:]
:匹配所有小写字母字符,等同于[a-z]
。
[:upper:]
:匹配所有大写字母字符,等同于[A-Z]
。
[:punct:]
:匹配所有标点符号字符。
[:space:]
:匹配所有空白字符,等同于\s
。
示例:字符类的使用
import re
# 匹配所有小写字母
pattern = r'[a-z]'
text = "Hello World!"
matches = re.findall(pattern, text)
print(matches) # 输出: ['e', 'l', 'l', 'o', 'o', 'r', 'l', 'd']
# 匹配所有数字字符
pattern = r'\d'
text = "Contact: 123-456-7890"
matches = re.findall(pattern, text)
print(matches) # 输出: ['1', '2', '3', '4', '5', '6', '7', '8', '9', '0']
# 使用POSIX字符类匹配所有字母字符
pattern = r'[[:alpha:]]'
text = "Regex 101!"
matches = re.findall(pattern, text)
print(matches) # 输出: ['R', 'e', 'g', 'e', 'x']
字符类可以与其他正则表达式元素结合使用,形成更加复杂的匹配模式。
# 匹配由字母和数字组成的字符串
pattern = r'\w+'
text = "User123 logged in."
matches = re.findall(pattern, text)
print(matches) # 输出: ['User123', 'logged', 'in']
# 匹配以小写字母开头且后面跟着数字的字符串
pattern = r'[a-z]\d+'
text = "a123 B456 c789"
matches = re.findall(pattern, text)
print(matches) # 输出: ['a123', 'c789']
正则表达式的语法规则是构建有效正则表达式的基础。以下是一些常见的语法规则:
|
来表示“或”,例如ab|cd
可以匹配“ab”或“cd”。()
来创建子表达式,允许对正则表达式的部分进行分组。\
来转义特殊字符,使其作为普通字符匹配。正则表达式除了基本的字符匹配和量词之外,还包含一些高级特性,用于构建更为复杂的匹配模式。
捕获组不仅可以用于分组,还可以在正则表达式的其他部分进行引用。引用捕获组可以通过反斜线加上捕获组的编号来实现。
()
:用来定义捕获组。\1
:表示对第一个捕获组的引用。import re
pattern = r'\b(\w+)\s+\1\b'
text = "This is a test test string"
match = re.search(pattern, text)
if match:
print(f"Matched: {match.group(0)}") # 输出: 'test test'
有时我们需要分组但不希望它被捕获用于后续引用,可以使用非捕获组(?:...)
。
pattern = r'(?:ab|cd)+'
text = "ababcdbcd"
matches = re.findall(pattern, text)
print(matches) # 输出: ['ababcd', 'bcd']
正则表达式的匹配模式默认是贪婪的,即它会尽可能多地匹配字符。可以通过在量词后加上?
来使匹配变为非贪婪的,匹配尽可能少的字符。
import re
text = "helloworld"
# 贪婪匹配
greedy_pattern = r'<.*>'
greedy_match = re.findall(greedy_pattern, text)
print(greedy_match) # 输出: ['helloworld']
# 非贪婪匹配
non_greedy_pattern = r'<.*?>'
non_greedy_match = re.findall(non_greedy_pattern, text)
print(non_greedy_match) # 输出: ['', '', '', '']
零宽断言用于在不消费字符的情况下进行匹配。它分为正向零宽断言(Lookahead)和反向零宽断言(Lookbehind)。
(?=...)
:正向零宽断言,表示某位置后必须匹配某模式。(?<=...)
:反向零宽断言,表示某位置前必须匹配某模式。(?!...)
:负向零宽断言,表示某位置后不能匹配某模式。(?:负向反向零宽断言,表示某位置前不能匹配某模式。
# 匹配'fox'前面是'quick'的单词
pattern = r'(?<=quick\s)fox'
text = "The quick brown fox jumps over the lazy dog"
match = re.search(pattern, text)
if match:
print(f"Matched: {match.group(0)}") # 输出: 'fox'
# 匹配'fox'后面跟随'jumps'的单词
pattern = r'fox(?=\sjumps)'
text = "The quick brown fox jumps over the lazy dog"
match = re.search(pattern, text)
if match:
print(f"Matched: {match.group(0)}") # 输出: 'fox'
使用正则表达式从HTML中提取特定内容。
import re
html_content = '''
'''
pattern = r'
images = re.findall(pattern, html_content)
print(images) # 输出: ['image1.png', 'image2.jpg', 'image3.gif']
在数据分析过程中,经常需要对数据进行清洗,去除无关字符或格式化数据。
import re
text = "Call us at (123) 456-7890 or 123.456.7890!"
cleaned_numbers = re.sub(r'[^\d]', '', text)
print(cleaned_numbers) # 输出: '12345678901234567890'
从HTML文档中提取所有的超链接。
import re
html_content = '''
Page 1
Page 2
Page 3
'''
pattern = r''
links = re.findall(pattern, html_content)
print(links) # 输出: ['http://example.com/page1', 'https://example.com/page2', 'http://example.com/page3']
提取HTML标签中的文本内容,如提取所有段落标签
中的文本。
import re
html_content = '''
This is the first paragraph.
Here is the second paragraph with a link.
And the third paragraph.
'''
pattern = r'(.*?)
'
paragraphs = re.findall(pattern, html_content, re.DOTALL)
print(paragraphs) # 输出: ['This is the first paragraph.', 'Here is the second paragraph with a link.', 'And the third paragraph.']
在处理API返回的JSON数据时,可以使用正则表达式快速提取特定的键值对。
import re
json_data = '''
{
"name": "John Doe",
"email": "[email protected]",
"phone": "+123-456-7890",
"address": "123 Main St, Anytown, USA"
}
'''
pattern = r'"phone":\s*"(.*?)"'
phone_number = re.search(pattern, json_data).group(1)
print(phone_number) # 输出: '+123-456-7890'
清理文本中的HTML标签,提取纯文本内容。
import re
html_content = '''
Title
This is a bold statement.
Here is a link and some italic text.
'''
clean_text = re.sub(r'<.*?>', '', html_content)
print(clean_text) # 输出: 'Title\nThis is a bold statement.\nHere is a link and some italic text.'
本文详细介绍了正则表达式的基础知识、语法规则及高级特性,并结合实际案例展示了正则表达式在编程中的重要作用。通过掌握正则表达式,你可以更高效地处理文本数据,解决各种复杂的字符串匹配问题。