Python中如何区分通配符字符串和正则表达式字符串,例如 `a.*` 与 `a\.*`?

如题,客户的奇葩需求,完全不知道没思路…
Python中如何区分通配符字符串和正则表达式字符串,例如 a.*a\.*

8 回复

回去把需求问透彻,问到有思路为止


在Python里,a.*a\.* 都是字符串,单从字符串本身无法直接、自动区分它们“想”被用作通配符还是正则表达式。关键在于你用什么函数去解释这个字符串。

简单来说:

  • a.*:如果被 re 模块(正则表达式)解释,点 . 是通配符(匹配任意字符),星号 * 是量词(匹配前一个字符0次或多次)。如果被 fnmatch 模块(通配符)解释,* 匹配任意字符序列,但 . 就是普通的点字符。
  • a\.*:如果被 re 模块解释,\. 是一个转义点(匹配字面意义的点字符),* 是量词。如果被 fnmatch 解释,\. 都是普通字符。

核心区别在于转义和使用的模块:

  1. 正则表达式 (re 模块):使用反斜杠 \ 进行转义。\. 表示字面意义的点,. 表示通配符。
  2. 通配符/文件名匹配 (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 个等级,可能对你有帮助

回到顶部