我正在尝试生成一个 Python 正则表达式字符串来验证列的值,这些值是来自三字母(大写)字母数字代码列表的逗号分隔的唯一三字母代码序列,例如 .该列表类似于 ['XA1', 'CZZ', 'BT9', 'WFF',...]
。因此有效的列值可以是 XA1
、XA1;CZZ
或 XA1;BT9;WFF;
等。代码不能出现在序列中 more不止一次。
有效序列必须是非空的,由唯一代码组成,并且可以或不可以以 ;
结尾,包括序列仅包含一个代码的情况。
如果 codes
是代码列表,那么我由此构造的正则表达式匹配字符串是
match_str = '?'.join(['({};){}'.format(code, '?' if codes[-1] == code else '') for code in codes])
这给了我,使用上面只有四个代码的示例列表
'(XA1;)?(CZZ;)?(BT9;)?(WFF;)?'
正则表达式匹配查询确实会为应该是有效序列的内容生成非空匹配对象,例如
re.match(match_str, 'XA1;')
re.match(match_str, 'XA1;WFF')
re.match(match_str, 'XA1;')
等等
In [124]: re.match(match_str, 'anystring')
Out[124]: <_sre.SRE_Match object; span=(0, 0), match=''>
In [125]: re.match(match_str, '')
Out[125]: <_sre.SRE_Match object; span=(0, 0), match=''>
In [126]: re.match(match_str, 'XA1;something')
Out[126]: <_sre.SRE_Match object; span=(0, 4), match='XA1;'>
我希望上面所有三个查询的结果都为空,所以我可以使用条件来过滤掉无效值,例如
if re.match(match_str, val):
# do something
else:
# do something else
最佳答案
在像您这样的情况下,应避免使用正则表达式,因为您希望使具有重复 block 的字符串失败。
使用“常规”Python:
codes = ['XA1', 'CZZ', 'BT9', 'WFF']
strs = ['XA1', 'XA1;CZZ', 'XA1;BT9;WFF;', 'XA1;XA1;', 'XA1;something']
for s in strs:
chunks = s.strip(';').split(';')
if set(chunks).issubset(codes) and len(chunks) == len(set(chunks)):
print("{}: Valid!".format(s))
else:
print("{}: Invalid!".format(s))
参见 Python demo online .
注意事项:
chunks = s.strip(';').split(';')
- 删除前导/尾随;
并用;< 拆分字符串
if set(chunks).issubset(codes) and len(chunks) == len(set(chunks)):
- 检查我们获得的所有 block 是否都是的子集编码
并确保block
中的每个项目都是唯一的。
正则表达式解决方案 - 不要在生产中使用!
import re
codes = ['XA1', 'CZZ', 'BT9', 'WFF']
block = "(?:{})".format("|".join(codes))
rex = re.compile( r"^(?!.*\b(\w+)\b.*\b\1\b){0}(?:;{0})*;?$".format(block) )
print(rex)
strs = ['XA1', 'XA1;CZZ', 'XA1;BT9;WFF;', 'XA1;XA1;', 'XA1;something']
for s in strs:
if rex.match(s):
print("{}: Valid!".format(s))
else:
print("{}: Invalid!".format(s))
参见 Python demo
关于python - 正则表达式匹配以分号分隔的标记序列的字符串,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56754034/