如何为行内有序列表创建正则表达式?
我有一个表单字段,这个字段只能包含内联的有序列表:
1. This item may be contain characters, symbols or numbers. 2. And this item also...
下面的代码无法对用户输入进行验证(用户只能输入内联的有序列表):
definiton_re = re.compile(r'^(?:\d\.\s(?:.+?))+$')
validate_definiton = RegexValidator(definiton_re, _("Enter a valid 'definition' in format: 1. meaning #1, 2. meaning #2...etc"), 'invalid')
附注:这里我使用的是Django框架中的RegexValidator类来验证表单字段的值。
2 个回答
0
这是我的解决方案。效果还不错。
input = '1. List item #1, 2. List item 2, 3. List item #3.'
regex = re.compile(r'(?:^|\s)(?:\d{1,2}\.\s)(.+?)(?=(?:, \d{1,2}\.)|$)')
# Parsing.
regex.findall(input) # Result: ['List item #1', 'List item 2', 'List item #3.']
# Validation.
validate_input = RegexValidator(regex, _("Input must be in format: 1. any thing..., 2. any thing...etc"), 'invalid')
validate_input(input) # No errors.
0
OP提供了一个不错的解决方案。 为了进一步优化,我们来做一些正则表达式的改进和简化。
(?<!\S)\d{1,2}\.\s((?:(?!,\s\d{1,2}\.),?[^,]*)+)
以下是新的内容:
(?:^|\s)
这个部分可以在选择中进行回溯匹配。我们这里用(?<!\S)
来替代,确保我们前面不是非空白字符。\d{1,2}\.\s
不需要放在一个非捕获组里。(.+?)(?=(?:, \d{1,2}\.)|$)
这个部分有点复杂。我们把它改成:(
捕获组-
(?:
-
(?!
负向前瞻:确保我们的位置不是: -
,\s\d{1,2}\.
一个逗号,空格字符,然后是列表索引。 -
)
-
,?[^,]*
这里是有趣的优化: - 如果有逗号,我们就匹配它。因为我们从前瞻中知道这个位置不是新列表索引的开始。因此,我们可以安全地假设后面的非逗号序列(如果有的话)与下一个元素无关,所以我们用
*
量词来处理它们,这样就没有回溯了。
- 如果有逗号,我们就匹配它。因为我们从前瞻中知道这个位置不是新列表索引的开始。因此,我们可以安全地假设后面的非逗号序列(如果有的话)与下一个元素无关,所以我们用
- 这比
(.+?)
有了显著的改进。
- 这比
-
)+
一直重复这个组,直到负向前瞻失败。 )
你可以用这个替代另一个答案中的正则表达式,这里有一个正则表达式演示!
不过,乍一看,这个问题用 re.split()
来解析会更好:
input = '1. List item #1, 2. List item 2, 3. List item #3.';
lines = re.split('(?:^|, )\d{1,2}\. ', input);
# Gives ['', 'List item #1', 'List item 2', 'List item #3.']
if lines[0] == '':
lines = lines[1:];
# Throws away the first empty element from splitting.
print lines;
这里有一个在线代码演示。
不幸的是,对于验证,你还是得用正则匹配的方法,只需在上面编译正则表达式:
regex = re.compile(r'(?<!\S)\d{1,2}\.\s((?:(?!,\s\d{1,2}\.),?[^,]*)+)')