Странное совпадение Objective-c NSRegularExpression

Мой шаблон NSString не работает.

NSString *pattern = @"/api/v1/news/([0-9]+)/\\?categoryId=([0-9]+)";
NSString *string = urlString;
NSRegularExpression *regex = [NSRegularExpression
                              regularExpressionWithPattern:pattern
                              options:NSRegularExpressionCaseInsensitive
                              error:nil];

Почему он соответствует и следующей строке?

/api/v1/news/123/?categoryId=22abc

Я хочу соответствовать только

/api/v1/news/123/?categoryId=22

где 123 и 22 могут быть переменными числами.


person Salvatore Cordiano    schedule 29.09.2015    source источник
comment
Покажите остальную часть кода, где вы получаете доступ к NSTextCheckingResult.   -  person zaph    schedule 30.09.2015
comment
Нажмите \b или $ в конце, чтобы убедиться, что путь заканчивается одной или несколькими цифрами.   -  person lintmouse    schedule 30.09.2015
comment
Руководство пользователя ICU: Регулярные выражения   -  person zaph    schedule 30.09.2015


Ответы (1)


Ваше регулярное выражение в порядке, но оно допускает частичные совпадения. Чтобы запретить их, используйте якоря ^ и $:

^/api/v1/news/([0-9]+)/\\?categoryId=([0-9]+)$
^                                            ^

См. демонстрацию регулярного выражения.

^ утверждает позицию в начале строки, а $ утверждает позицию в конце строки.

См. также демонстрацию IDEONE, показывающую NO MATCH для первой введенной строки, и эта демонстрация соответствует второй.

Если вам нужно сопоставить эти строки как отдельные слова, используйте \\b (граница слова) в конце и (?<!\\w) обратного просмотра (убедитесь, что перед этим нет символа слова) в начале:

(?<!\\w)/api/v1/news/([0-9]+)/\\?categoryId=([0-9]+)\\b
^^^^^^^^                                             ^^

Если вам также нужен доступ к захваченным текстам, используйте что-то вроде:

NSString *pattern = @"^/api/v1/news/([0-9]+)/\\?categoryId=([0-9]+)$";
NSString *string = @"/api/v1/news/123/?categoryId=22";
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error];
NSTextCheckingResult *match = [regex firstMatchInString:string 
                            options:0 
                            range:NSMakeRange(0, string.length)];
NSLog(@"Group 1 number: %@", [string substringWithRange:[match rangeAtIndex:1]]);
NSLog(@"Group 2 number: %@", [string substringWithRange:[match rangeAtIndex:2]]);

См. демонстрацию IDEONE.

Group 1 number: 123
Group 2 number: 22
person Wiktor Stribiżew    schedule 29.09.2015