正则表达式仅匹配用逗号分隔的唯一名称

时间:2019-01-11 18:33:40

标签: python regex expression

我正在使用正则表达式来检查字符串的有效性。 特别是,如果字符串包含唯一的大写名称(一个或多个),并且最终由逗号分隔,我希望通过测试。

每个名称长度应在 3 20 之间。

可接受的字符串:

  

JOHN,MARK,EDDIE

     

JOHN

不接受字符串:

  

JOHN,

     

约翰·马克

     

JOHN ,MARK,EDDIE, JOHN

我正在使用以下正则表达式来确保名称必须用逗号分隔(如果有多个),但是如何分辨名称是唯一的呢?

^([A-Z]{3,20})(,[A-Z]{3,20})*$

2 个答案:

答案 0 :(得分:1)

您可以使用negative lookaheadquotesmatched name

(?!.*\2)

re.match(r'^(([A-Z]{3,20})(?![A-Z,]*,\2,),)+$', string + ',') 部分确保以后不会出现匹配的名称。这是如何使用负前瞻的示例。根据OP要求的完整正则表达式为:

string + ','

请注意,这是针对t = a*N**2 + c(即附加了一个人工逗号)进行的测试,以避免在第一部分和后续部分混淆两个不同的组。

我认为负先行短路是指一旦遇到匹配便会失败。这意味着最坏情况下的性能应为O(N ^ 2)。我们可以通过生成仅包含唯一名称的字符串并检查正则表达式的性能来进行检查。二次拟合得到a = 0.06 us, c = 3 usfrom random import choice, sample from string import ascii_lowercase as lowercase import re import time N = 500 data = [None] * N for i in range(N): length = choice(range(3, 21)) x = ''.join(sample(lowercase, length)) while sample in data: length = choice(range(3, 21)) x = ''.join(sample(lowercase, length)) data[i] = x pattern = re.compile(r'^(([a-z]+),?(?!.*\2))+$') timings = [] for i in range(2, N+1): print('Begin iteration. ', end='', flush=True) string = ','.join(data[:i]) print(f'Run for {i} unique names (lenght = {len(string)}) ... ', end='', flush=True) t1 = time.clock() m = re.match(pattern, string) t2 = time.clock() print('done.', end='', flush=True) assert m is not None timings.append(t2 - t1) print(' End iteration.', flush=True)

Timing plot

代码

antMatchers("/**/**").permitAll()

答案 1 :(得分:0)

您可能要做的是先使用正则表达式查找没有捕获组的有效字符串:

^[A-Z]{3,20}(?:,[A-Z]{3,20})*$

如果字符串有效,则可以用逗号分隔,并使用set将项目的长度与项目的长度进行比较,以使其唯一。 如果这些值匹配,则您的字符串有效。

例如

import re
strings = ["JOHN,MARK,EDDIE", "JOHN", "JOHN,", "JOHN MARK", "JOHN,MARK,EDDIE,JOHN"]

for s in strings:
    m = re.match("^[A-Z]{3,20}(?:,[A-Z]{3,20})*$", s)

    if m:
        parts = s.split(',')
        res = len(parts) == len(set(parts))
        print("{}:{}".format(s, res))

结果

JOHN,MARK,EDDIE:True
JOHN:True
JOHN,MARK,EDDIE,JOHN:False

请参见regex demo | Python demo