问题描述
我想自动分析所有当前类型字符的字符串,并基于带有示例模板的列创建一个 RegEx 模式。
这样以后与此模式相关的任何字符串都可以仅通过允许的字符进行清理,然后与模式对齐。
例如样本可以是:
"A111AA1" - 表示所有可能的字符:只有字母和数字;模式应该是:第一个字母,然后是 3 个数字,然后是 2 个字母和 1 个数字。
"11AA-111A" - 表示可能的字符:字母、数字、连字符/破折号;模式:2 位数字、2 个字母、破折号、3 位数字、1 个字母。
是否可以不手动进行 if-else 硬编码?独特的模式可能 > 1000。
谢谢。
更新
关于在字符串中提取所有可能的字符,我创建了以下函数。它使用模式中现有的(允许的)字符创建 RegEx。
如果你知道更好的方法,请告诉我。
def extractCharsFromPattern(pattern: str) -> str:
allowedChars = []
# Convert string to set of chars
pattern = ''.join(set(pattern))
# Letters
if re.findall(r"[a-zA-Z]",pattern):
allowedChars.append("a-zA-Z")
pattern = re.sub(r"[a-zA-Z]","",pattern)
# Digits
if re.findall(r"[0-9]",pattern):
allowedChars.append("0-9")
pattern = re.sub(r"[0-9]",pattern)
# Special chars
allowedChars.append(pattern)
# Prepare in regex format
allowedChars = "[" + "".join(allowedChars) + "]"
return allowedChars
解决方法
如果您的模式如此简单,那么您当然可以对其进行匹配以获得正则表达式,例如:
patterns = ["A111AA1","11AA-111A"]
for pattern in patterns:
re_pattern = ''.join([r'\d' if c.isdigit() else r'[a-zA-Z]' if c.isalpha() else r'-' if c=='-' else '???' for c in pattern])
print (pattern,'-->',re_pattern)
A111AA1 --> [a-zA-Z]\d\d\d[a-zA-Z][a-zA-Z]\d
11AA-111A --> \d\d[a-zA-Z][a-zA-Z]-\d\d\d[a-zA-Z]
根据您的评论,如果您只想要一个字符类,您可以将它们链接在一起。这是一个单行示例,但根据您的要求,您可以将其放入函数中:
>>> s="AA-22"
>>> r = ('[' # start of character class
+ ('a-z' if re.search(r'[a-z]',s) else '') # have a lowercase?
+ ('A-Z' if re.search(r'[A-Z]',s) else '') # have an uppercase?
+ ('0-9' if re.search(r'[0-9]',s) else '') # have a number?
+ ('-' if re.search(r'-',s) else '') # have a dash
+ ']' # end of character class
+ '{' + str(len(s)) + '}' # enforce a length?
)
# '[A-Z0-9-]{5}'
>>> re.search(r,"BB-44").group(0)
# 'BB-44'