Lookahead регулярное выражение - PullRequest
0 голосов
/ 27 января 2012

Я ищу соответствующий шаблон

(1)

10 цифр Sometext (например, 1235873490 ABCD EFGK)

В тексте, который может иметь шаблон выше, а также очень похожий шаблон, как этот

(2) * * +1011

10 цифр sometext decimal_number (например, 9835873490 VBGF XMF 23,233)

Как мне написать регулярное выражение, чтобы оно соответствовало только шаблону (1) и игнорировало шаблон (2)?

Я смотрел на негативных взглядов, используя что-то вроде этого:

(\d{10})\s*([A-Za-z0-9]+(?:\s+[A-Za-z0-9]+)(?:\s+[A-Za-z0-9]+))\s*(?!(\d+.\d+))

но не могу заставить его работать. Есть идеи? Кстати, я использую c ++ boost :: regex.

1 Ответ

2 голосов
/ 27 января 2012

Во-первых, начните с простой версии:

(\d{10}         # 10 digits
    (?:\s+\w+)+)  # some text, separated by spaces,
                  # at least one time
(?!\s*\d+\.\d+) # not followed by a decimal number

Я изменил ваш [A-Za-z0-9] на \w для простоты и позволил этому происходить столько раз, сколько он хочет.

Тем не менее, это также будет соответствовать второй строке - она ​​сожрет 23 в конце, а затем увидит, что после нее не следует десятичное число (за которым следует ".23"), поэтому оно будет совпадать.

Чтобы предотвратить это, мы можем сказать, что за ним должен следовать пробел или конец текста:

(\d{10}(?:\s+\w+)+)
    (?=\s|$)      # it must be followed by a space or end of text
(?!\s*\d+\.\d+)

Однако это все еще имеет проблему.Теперь он будет соответствовать «... XMF», но затем увидим, что за ним следует десятичное число и возврат.Он вернется к «... VBGF» и затем совпадет, так как «VBGF» не следует после десятичной дроби.

Чтобы предотвратить это, мы можем сказать регулярному выражению, что оно не может вернуться назад, как только оносоответствует нашему основному разделу:

(?> # added '?>': not allowed to backtrack once this group is matched
    \d{10}(?:\s+\w+)+)      
(?=\s|$)(?!\s*\d+\.\d+)

В качестве альтернативы, если вы знаете, что всегда будет 2 части в sometext , это также решит проблему с возвратом:

 (\d{10}(?:\s+\w+){2}  # can only occur twice
     )    
 (?=\s|$)(?!\s*\d+\.\d+)
...