Python中如何区分通配符字符串和正则表达式字符串,例如 `a.*` 与 `a\.*`?
如题,客户的奇葩需求,完全不知道没思路…
Python中如何区分通配符字符串和正则表达式字符串,例如 a.* 与 a\.*?
8 回复
回去把需求问透彻,问到有思路为止
在Python里,a.* 和 a\.* 都是字符串,单从字符串本身无法直接、自动区分它们“想”被用作通配符还是正则表达式。关键在于你用什么函数去解释这个字符串。
简单来说:
a.*:如果被re模块(正则表达式)解释,点.是通配符(匹配任意字符),星号*是量词(匹配前一个字符0次或多次)。如果被fnmatch模块(通配符)解释,*匹配任意字符序列,但.就是普通的点字符。a\.*:如果被re模块解释,\.是一个转义点(匹配字面意义的点字符),*是量词。如果被fnmatch解释,\和.都是普通字符。
核心区别在于转义和使用的模块:
- 正则表达式 (
re模块):使用反斜杠\进行转义。\.表示字面意义的点,.表示通配符。 - 通配符/文件名匹配 (
fnmatch模块):通常不使用反斜杠转义特殊字符(*,?,[)。在fnmatch看来,\就是一个普通字符。
代码示例:
import re
import fnmatch
pattern_str1 = "a.*"
pattern_str2 = "a\\.*" # 注意:在Python字符串中,要表示一个反斜杠,需要写两个:`\\`
test_string = "a.txt"
# 1. 用作正则表达式
print("作为正则表达式匹配:")
print(f" re.match(r'{pattern_str1}', '{test_string}'): {bool(re.match(pattern_str1, test_string))}") # True, `.` 匹配了 `t`
print(f" re.match(r'{pattern_str2}', '{test_string}'): {bool(re.match(pattern_str2, test_string))}") # False, `\.` 要求字面点,但字符串是 `a.txt`
# 匹配 `a.*` 这个字面字符串
print(f" re.match(r'{pattern_str2}', 'a.*'): {bool(re.match(pattern_str2, 'a.*'))}") # True, `\.` 匹配 `.`, `*` 匹配 `*`
# 2. 用作通配符 (fnmatch)
print("\n作为通配符匹配 (fnmatch):")
print(f" fnmatch.fnmatch('{test_string}', '{pattern_str1}'): {fnmatch.fnmatch(test_string, pattern_str1)}") # True, `*` 匹配了 `.txt`
print(f" fnmatch.fnmatch('{test_string}', '{pattern_str2}'): {fnmatch.fnmatch(test_string, pattern_str2)}") # False, 它把 `\` 当作普通字符,所以字面上匹配 `a\\.*`
print(f" fnmatch.fnmatch('a.*', '{pattern_str2}'): {fnmatch.fnmatch('a.*', pattern_str2)}") # False,原因同上
print(f" fnmatch.fnmatch('a\\.*', '{pattern_str2}'): {fnmatch.fnmatch('a\\.*', pattern_str2)}") # True,完全字面匹配
总结: 一个字符串是通配符还是正则表达式,取决于你把它传给 re 还是 fnmatch 去处理。
奇葩+1,你看看正式环境和需求文档吧,一般就判断除 26 个英文字母之外其他都是正则吧,一大堆 if 和 eles 正在赶来的路上
a.*也是合法正则啊
另外,这种规则,如果是让用户输入字符串,根本没有用户知道怎么用
用函数来开始啊,比如在要用到正则的时候需要用某函数才算正则,不然的话就当普通来算
两种都是合法的正则。。。
a..
了解一下 Vim 正则使用的 4 个等级,可能对你有帮助

