正则表达式

本文详细介绍了正则表达式的使用规则,包括通配符、字符集、重复模式、边界匹配等,并通过Notepad++、PyCharm和Python的re模块展示了搜索、分割和查找功能的应用。同时,对比了贪婪模式和懒惰模式的区别,以及在Java中的String和Pattern类的使用方法。
摘要由CSDN通过智能技术生成

使用规则

字符含义
普通字符只与自己匹配,作为字面字符
通配符(.)除换行符(\r、\n)外的任何单个字符匹配。
Python的re.DOTALL/re.S模式 或 notepad++的“.匹配新行”模式,通配符可以与换行符匹配,Pycharm不支持。
字符集 (-)匹配范围内的单个字符,例如[pj]、[a-z]、[a-zA-Z0-9]
排除字符集(^)例如[^abc]与除a、b、c外的其他任何单个字符都匹配
二选一(|)python|perl 匹配 python或python
子模式(小括号)例如p(ython|erl)
可选模式(?)放在子模式后面,将其指定为可选的。例如abc?与ab和abc匹配。
?默认为贪婪模式,即尽量匹配更长的字符串,从后面添加?可以变为??非贪婪模式
重复模式(*+{ })(pattern)*:pattern可重复0、1或多次。
(pattern)+:pattern可重复1或多次。
(pattern){m, n}:模式可重复m~n次,也可以是{n}、{m, }。
* + {m, n} {m, }默认为贪婪模式,即尽量匹配更长的字符串,从后面添加?可以变为*? +? {m, n}? {m, }?非贪婪模式
字符串开头(^)和结尾($)例如(^http)与http开头的字符串匹配,(org$)与org结尾的字符串匹配
python默认为单行模式,即^匹配第一行的开头,$匹配最后一行的结尾,
re.M或re.MULTILINE(多行模式)^$分别可以匹配每一行文本的开头和结尾。例如在 ‘foo1\nfoo2\n’ 或 ‘foo1\nfoo2’ 中搜索 foo.$,通常匹配 ‘foo2’,但在 MULTILINE 模式下可以匹配到 ‘foo1’。
例如在默认单行模式下’ddddd\nabbbc’搜索’^a.*c$'失败,但多行模式下搜索结果为(6, 11)。
pycharm和notepad++默认且只能是多行模式
\d匹配所有的十进制数字
\D匹配所有的非十进制数字(包括换行符)
\s匹配所有的空白字符(空格、TAB等)
\S匹配所有的非空白字符(包括换行符)
\w匹配所有的字母、汉字、数字、下划线
\W匹配所有的非字母、汉字、数字、下划线(包括换行符)
\b(根据例子理解)匹配在单词开始或结尾位置的空字符串。r’\bfoo\b’匹配’foo’, ‘foo.’, ‘(foo)’, ‘bar foo baz’但不匹配’foobar’, ‘foo3’。
\B(根据例子理解) 匹配不在单词开始或结尾位置的空字符串。r’py\B’匹配’python’, ‘py3’, ‘py2’但不匹配’py’, ‘py.’, ‘py!’。

注意:

  1. 匹配特殊字符时,需要使用\进行转义。例如要匹配字符串中’python.org’,因为.是特殊字符(通配符),所以要对其进行转义,表达式应该为’python\\.org’(这里包括两层转义:解释器执行的转义和模块re执行的转义,因为在字符串中\为转义字符,所以\\才表示一个真正的\),也可以使用原始字符串r’python\.org’
  2. (重要)贪婪模式 vs. 懒惰模式(易错)
    经常看到,贪婪模式(默认)寻求最长匹配,懒惰模式寻求最短匹配。直观上,abbb查询ab?? 结果应是a,aaab查询标记a??b结果应是b,但aaab查询标记a??b的结果实际是ab,即这样理解是错误的。
    实际上应该这样理解,懒惰模式一旦找到符合的匹配即作为查询结果返回,贪婪模式(默认)找到符合的匹配后,不断向后添加字符至匹配失败,失败前一步的字符串作为查询结果返回。为了方便理解,可以认为匹配过程是将子串string[s, e](s从0到n-1,e从s+1到n)与查询串pattern的(1+n)*n/2次比较过程。

Notepad++

windows notepad++换行符是\r\n

“Ctrl+F”,弹出查找窗口,如下图所示
在这里插入图片描述
匹配大小写:勾选时匹配大小写
.匹配新行:不勾选时通配符(.)不能匹配(\r、\n),勾选时通配符(.)能匹配(\r、\n)

PyCharm

在这里插入图片描述
匹配大小写:勾选时匹配大小写

Python

re模块官方API
主串:被查询的长字符串;模式串:作为查询关键字的短字符串

compile

# 使用模式串pattern(str类型)构建正则表达式对象
re.compile(pattern, flags=0)

# 常用flag,可以用“|”将多个flag连接起来
# 忽略大小写
re.I
re.IGNORECASE
# 多行模式
re.M
re.MULTILINE
# .匹配新行
re.S
re.DOTALL

search

# 返回第一个位置的 匹配对象(re.Match object) 或 None
# 两种调用方式的函数原型
re.search(pattern, string, flags=0)
Pattern.search(string[, pos[, endpos]])

# 调用方式1(模式串str,主串str,flags)
re.search(pattern, string, flags)
# 调用方式2(模式串str,flags;主串str,开始位置int,结束位置int)
prog = re.compile(pattern, flags)
prog.search(string, pos ,endpos)

# 例如
result = re.search('345', '123456')
print(result.start(), result.end())
# 2 5

prog = re.compile('345')
result = prog.search('123456')
print(result.start(), result.end())
# 2 5

split

# 分割字符串
re.split(pattern, string, maxsplit=0, flags=0)
Pattern.split(string, maxsplit=0)

>>> re.split(r'\W+', 'Words, words, words.')
['Words', 'words', 'words', '']
# 添加括号后,用来分割的字符也将作为返回值
>>> re.split(r'(\W+)', 'Words, words, words.')
['Words', ', ', 'words', ', ', 'words', '.', '']
>>> re.split(r'\W+', 'Words, words, words.', 1)
['Words', 'words, words.']
>>> re.split('[a-f]+', '0a3B9', flags=re.IGNORECASE)
['0', '3', '9']
>>> re.split(r'(\W+)', '...words, words...')
['', '...', 'words', ', ', 'words', '...', '']

>>> re.split(r'\b', 'Words, words, words.')
['', 'Words', ', ', 'words', ', ', 'words', '.']
# 注意,*是可以匹配到空字符串的(+不能),所以此处的r'\W*'成功匹配8次(包含6次空字符串匹配)
>>> re.split(r'\W*', '...words...')
['', '', 'w', 'o', 'r', 'd', 's', '', '']
>>> re.split(r'(\W*)', '...words...')
['', '...', '', '', 'w', '', 'o', '', 'r', '', 'd', '', 's', '...', '', '', '']
# r'\w*'成功匹配8次(包含7次空字符串匹配)
>>> re.split(r'\w*', '...words...')
['', '.', '.', '.', '', '.', '.', '.', '']
>>> re.split(r'(\w*)', '...words...')
['', '', '.', '', '.', '', '.', 'words', '', '', '.', '', '.', '', '.', '', '']

findall

# 返回pattern在string中所有非重叠匹配的字符串列表
re.findall(pattern, string, flags=0)
Pattern.findall(string[, pos[, endpos]])

# 例如
>>> re.findall(r'\bf[a-z]*', 'which foot or hand fell fastest')
['foot', 'fell', 'fastest']

Java

String

// obj和regex严格的完全匹配
public boolean matches(String regex);

public String replaceFirst(String regex, String replacement);

public String replaceAll(String regex, String replacement);

public String[] split(String regex, int limit);

public String[] split(String regex);

Pattern

无构造函数,只能通过compile构造Pattern对象

// 静态方法
public static Pattern compile(String regex);
// flags: CASE_INSENSITIVE, MULTILINE, DOTALL, UNICODE_CASE, CANON_EQ, UNIX_LINES, LITERAL, UNICODE_CHARACTER_CLASS and COMMENTS
public static Pattern compile(String regex, int flags);
// regex和input严格的完全匹配
// CharSequence: 接口,常见实现类有:String StringBuffer StringBuilder CharBuffer
public static boolean matches(String regex, CharSequence input);

// 实例方法
// Predicate<T>:函数式接口,有boolean test(T t)方法
// obj和t严格的完全匹配
public Predicate<String> asMatchPredicate();
// obj出现在t中
public Predicate<String> asPredicate();
public String[] split(CharSequence input);
public String[] split(CharSequence input, int limit); 
public Stream<String> splitAsStream(final CharSequence input); 
    
// 生成Matcher对象
public Matcher matcher(CharSequence input);

Matcher

无构造函数,只能通过Pattern类的matcher方法构造Matcher对象

// 常用实例方法
// 查找str中与Patter对象匹配的下一个区间
// 存在返回true,否则返回false
public boolean find()
// 当前区间起始值
public int start()
// 当前区间终止值
public int end()
// 重置Matcher
public Matcher reset()

示例

public class Main {
    public static void main(String[] args) {
        Pattern pattern = Pattern.compile("\\d+");
        Matcher matcher = pattern.matcher("aaa54bb666");
        while (matcher.find()) {
            System.out.println(String.format("(%d, %d)", matcher.start(), matcher.end()));
        }
        // (3, 5)
        // (7, 10)
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MallocLu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值