正则表达式是一种由字符和操作符组成的模式,用来描述字符串的特征,通过正则表达式可以搜索、替换、提取和匹配特定模式的文本数据。
常用元字符
.
匹配除换行符”\n”以外的任意字符
\\
转义字符,用于匹配元字符时的转义,匹配元字符时用”\\元字符”
^
匹配字符串的开始位置
$
匹配字符串的结束位置
*
匹配前一个元素零次或多次
+
匹配前一个元素一次或多次
?
匹配前一个元素零次或一次
[]
匹配方括号内的任意一个字符
[^]
否定字符类,匹配不在方括号内的任意字符
()
分组操作符,用于分组匹配模式
|
或操作符,匹配多个模式中的任意一个
\d
匹配一个数字字符,等效于[0-9]
\D
匹配一个非数字字符,等效于[^0-9]
\w
匹配一个字母数字字符,等效于[A-Za-z0-9_]
\W
匹配一个非字母数字字符,等效于[^A-Za-z0-9_]
\s
匹配一个空白字符,包括空格、制表符、换行符等
\S
匹配一个非空白字符
[\u4e00-\u9fa5]+
匹配Unicode编码中文文本
直接匹配
使用stringr
包
str_extract
只找到第一个匹配的部分
str_extract_all
寻找所有的匹配
library (stringr)
text <- c ("Hello123!@#(+)10%+" , "30%-Hello123!@#中(+)" , "好Hello123(-)0+" )
str_extract (text, " \\ d+%" )
str_extract_all (text, " \\ d+%" )
[[1]]
[1] "10%"
[[2]]
[1] "30%"
[[3]]
character(0)
str_extract (text, " \\ d+%?" )
str_extract_all (text, " \\ d+%?" )
[[1]]
[1] "123" "10%"
[[2]]
[1] "30%" "123"
[[3]]
[1] "123" "0"
使用re
库匹配数据
re.search
只找到第一个匹配的部分
re.findall
寻找所有的匹配
import re
text = ["Hello123!@#(+)10%+" , "30%-Hello123!@#中(+)" , "好Hello123(-)0+" ]
[re.search(r"\d+%" , t).group() if re.search(r"\d+%" , t) else None for t in text]
[re.findall(r"\d+%" , t) for t in text]
零宽断言
零宽断言是一种特殊的正则表达式语法,用于在匹配文本时添加额外的条件,但不包括在最终的匹配结果中。它可以用来指定匹配位置的前后必须满足的条件。常见的零宽断言包括:
正向顺序零宽断言(正向先行断言):(?=…),表示匹配位置的后面必须满足指定条件。
负向顺序零宽断言(负向先行断言):(?!…),表示匹配位置的后面不能满足指定条件。
正向逆序零宽断言(正向后行断言):(?<=…),表示匹配位置的前面必须满足指定条件。
负向逆序零宽断言(负向后行断言):(?<!…),表示匹配位置的前面不能满足指定条件。
library (stringr)
x <- c (
"172.10.20.70(上海-上海)" , "192.168.20.10(湖北-武汉)" ,
"173.20.10.70(河北-石家庄)"
)
# 提取省份
str_extract (x, pattern = "(?<= \\ () \\ w+(?=-)" )
# 提取 IP
str_extract (x, pattern = ".*(?= \\ ()" )
[1] "172.10.20.70" "192.168.20.10" "173.20.10.70"
import re
text = [
"172.10.20.70(上海-上海)" , "192.168.20.10(湖北-武汉)" ,
"173.20.10.70(河北-石家庄)"
]
# 提取省份
[re.search(r"(?<=\()\w+(?=-)" ,t).group() for t in text]
# 提取 IP
[re.search(".*(?= \\ ()" ,t).group() for t in text]
['172.10.20.70', '192.168.20.10', '173.20.10.70']
分组捕获
分组捕获是指在正则表达式中使用小括号将一部分模式进行分组,并且可以对分组进行捕获或者不捕获。分组捕获可以帮助我们提取匹配到的部分,或者对匹配到的部分进行后续操作。常见的分组捕获语法包括:
# 捕获型分组示例
text <- "apple, banana, cherry"
pattern <- "( \\ w+), ( \\ w+), ( \\ w+)"
match <- regexec (pattern, text)
if (length (match[[1 ]]) >= 0 ) {
print ("捕获型分组示例:" )
matched_text <- regmatches (text, match)[[1 ]]
print (str_c ("整体匹配结果:" , matched_text[1 ]))
print (str_c ("第一个捕获组:" , matched_text[2 ]))
print (str_c ("第二个捕获组:" , matched_text[3 ]))
print (str_c ("第三个捕获组:" , matched_text[4 ]))
}
[1] "捕获型分组示例:"
[1] "整体匹配结果:apple, banana, cherry"
[1] "第一个捕获组:apple"
[1] "第二个捕获组:banana"
[1] "第三个捕获组:cherry"
# 非捕获型分组示例
text <- "apple, banana, cherry"
pattern <- "(?: \\ w+), ( \\ w+), ( \\ w+)"
match <- regexec (pattern, text)
if (length (match[[1 ]]) >= 0 ) {
print (" \n 非捕获型分组示例:" )
matched_text <- regmatches (text, match)[[1 ]]
print (str_c ("整体匹配结果:" , matched_text[1 ]))
print (str_c ("第一个捕获组:" , matched_text[2 ]))
print (str_c ("第二个捕获组:" , matched_text[3 ]))
}
[1] "\n非捕获型分组示例:"
[1] "整体匹配结果:apple, banana, cherry"
[1] "第一个捕获组:banana"
[1] "第二个捕获组:cherry"
# 捕获后替换
library (stringr)
text <- "apple, banana, cherry"
pattern <- "( \\ w+), ( \\ w+), ( \\ w+)"
result <- str_replace (text, pattern, " \\ 1 - \\ 2 - \\ 3" )
print (result)
[1] "apple - banana - cherry"
import re
# 捕获型分组示例
text = "apple, banana, cherry"
pattern = r"(\w+), (\w+), (\w+)"
match = re.match(pattern, text)
if match:
print ("捕获型分组示例:" )
print ("整体匹配结果:" , match.group(0 ))
print ("第一个捕获组:" , match.group(1 ))
print ("第二个捕获组:" , match.group(2 ))
print ("第三个捕获组:" , match.group(3 ))
捕获型分组示例:
整体匹配结果: apple, banana, cherry
第一个捕获组: apple
第二个捕获组: banana
第三个捕获组: cherry
# 非捕获型分组示例
text = "apple, banana, cherry"
pattern = r"(?:\w+), (\w+), (\w+)"
match = re.match(pattern, text)
if match:
print (" \n 非捕获型分组示例:" )
print ("整体匹配结果:" , match.group(0 ))
print ("第一个捕获组:" , match.group(1 ))
print ("第二个捕获组:" , match.group(2 ))
非捕获型分组示例:
整体匹配结果: apple, banana, cherry
第一个捕获组: banana
第二个捕获组: cherry
# 捕获后替换
import re
text = "apple, banana, cherry"
pattern = r'(\w+), (\w+), (\w+)'
result = re.sub(pattern, r'\1 - \2 - \3' , text)
print (result)
多行模式
使用多行正则匹配模式可以方便地处理包含换行符的文本,从而实现对多行内容的精确匹配和提取。在多行模式下,会针对每一行进行正则匹配,这在处理日志文件、文本文档等需要跨行匹配的场景中非常有用。
text <- "Line 1 \n Line \n Line 3"
pattern <- regex ("(Line \\ d$)" , multiline = TRUE )
matches <- str_extract_all (text, pattern)
print (matches)
[[1]]
[1] "Line 1" "Line 3"
import re
text = "Line 1 \n Line \n Line 3"
pattern = r"(Line \d$)"
matches = re.findall(pattern, text, flags= re.MULTILINE)
print (matches)
正则推断
inferregex
包可以根据字符串自动推断生成正则表达式
# pak::pkg_install("daranzolin/inferregex")
library (inferregex)
s <- "apple, banana, cherry"
infer_regex (s)$ regex
[1] "^[a-z]{5},\\s[a-z]{6},\\s[a-z]{6}$"
回到顶部