#objective-c #regex #nsregularexpression
#objective-c #регулярное выражение #nsregularexpression
Вопрос:
Основная проблема: ObjC может сказать мне, что было шесть совпадений, когда мой шаблон, @"\b(\S )\b"
, но когда мой шаблон @"A b (c) or (d)"
, он сообщает только об одном совпадении, "c"
.
Решение
Вот функция, которая возвращает группы захвата в виде NSArray . Я новичок в Objective C, поэтому я подозреваю, что есть лучшие способы выполнить неуклюжую работу, чем путем создания изменяемого массива и присвоения его в конце NSArray.
- (NSArray *)regexWithResults:(NSString *)haystack pattern:(NSString *)strPattern
{
NSArray *ar;
ar = [[NSArray alloc] init];
NSError *error = NULL;
NSArray *arTextCheckingResults;
NSMutableArray *arMutable = [[NSMutableArray alloc] init];
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:strPattern
options:NSRegularExpressionSearch error:amp;error];
arTextCheckingResults = [regex matchesInString:haystack
options:0
range:NSMakeRange(0, [haystack length])];
for (NSTextCheckingResult *ntcr in arTextCheckingResults) {
int captureIndex;
for (captureIndex = 1; captureIndex < ntcr.numberOfRanges; captureIndex ) {
NSString * capture = [haystack substringWithRange:[ntcr rangeAtIndex:captureIndex]];
//NSLog(@"Found '%@'", capture);
[arMutable addObject:capture];
}
}
ar = arMutable;
return ar;
}
Проблема
Я привык использовать круглые скобки для сопоставления групп захвата в Perl таким образом:
#!/usr/bin/perl -w
use strict;
my $str = "This sentence has words in it.";
if(my ($what, $inner) = ($str =~ /This (S ) has (S ) in it/)) {
print "That $what had '$inner' in it.n";
}
Этот код приведет к:
В этом предложении были "слова".
Но в Objective C с помощью NSRegularExpression мы получаем разные результаты. Пример функции:
- (void)regexTest:(NSString *)haystack pattern:(NSString *)strPattern
{
NSError *error = NULL;
NSArray *arTextCheckingResults;
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:strPattern
options:NSRegularExpressionSearch
error:amp;error];
NSUInteger numberOfMatches = [regex numberOfMatchesInString:haystack options:0 range:NSMakeRange(0, [haystack length])];
NSLog(@"Pattern: '%@'", strPattern);
NSLog(@"Search text: '%@'", haystack);
NSLog(@"Number of matches: %lu", numberOfMatches);
arTextCheckingResults = [regex matchesInString:haystack options:0 range:NSMakeRange(0, [haystack length])];
for (NSTextCheckingResult *ntcr in arTextCheckingResults) {
NSString *match = [haystack substringWithRange:[ntcr rangeAtIndex:1]];
NSLog(@"Found string '%@'", match);
}
}
Вызывает эту тестовую функцию, и результаты показывают, что она способна подсчитывать количество слов в строке:
NSString *searchText = @"This sentence has words in it.";
[myClass regexTest:searchText pattern:@"\b(\S )\b"];
Шаблон: ' b( S ) b' Текст для поиска: "В этом предложении есть слова". Количество совпадений: 6 Найдена строка 'This' Найдена строка 'предложение' Найденная строка 'имеет' Найденная строка "слова" Найдена строка 'in' Найденная строка 'it'
Но что, если группы захвата являются явными, например, так?
[myClass regexTest:searchText pattern:@".*This (sentence) has (words) in it.*"];
Результат:
Шаблон: '.* В этом (предложении) есть (слова). *' Текст поиска: "В этом предложении есть слова". Количество совпадений: 1 Найдена строка 'предложение'
То же, что и выше, но с S вместо фактических слов:
[myClass regexTest:searchText pattern:@".*This (\S ) has (\S ) in it.*"];
Результат:
Шаблон: '.* В этом (S ) есть (S ) .*' Текст поиска: "В этом предложении есть слова". Количество совпадений: 1 Найдена строка 'предложение'
Как насчет подстановочного знака в середине?
[myClass regexTest:searchText pattern:@"^This (\S ) .* (\S ) in it.$"];
Результат:
Шаблон: '^Это (S ) .* ( S ) в нем.$' Текст поиска: "В этом предложении есть слова". Количество совпадений: 1 Найдена строка 'предложение'
Ссылки: NSRegularExpression
NSTextCheckingResult
Параметры сопоставления NSRegularExpression
Комментарии:
1. Это также может быть связано с тем, как я использую NSTextCheckingResult.
Ответ №1:
Я думаю, если вы измените
// returns the range which matched the pattern
NSString *match = [haystack substringWithRange:ntcr.range];
Для
// returns the range of the first capture
NSString *match = [haystack substringWithRange:[ntcr rangeAtIndex:1]];
Вы получите ожидаемый результат для шаблонов, содержащих один захват.
Смотрите страницу документа для NSTextCheckingResult:rangeAtIndex:
Результат должен иметь хотя бы один диапазон, но может необязательно иметь больше (например, для представления групп захвата регулярных выражений).
Передача rangeAtIndex: значение 0 всегда возвращает значение свойства range . Дополнительные диапазоны, если таковые имеются, будут иметь индексы от 1 до numberOfRanges-1.
Ответ №2:
Измените NSTextCheckingResult
:
- (void)regexTest:(NSString *)haystack pattern:(NSString *)strPattern
{
NSError *error = NULL;
NSArray *arTextCheckingResults;
NSRegularExpression *regex = [NSRegularExpression
regularExpressionWithPattern:strPattern
options:NSRegularExpressionSearch
error:amp;error];
NSRange stringRange = NSMakeRange(0, [haystack length]);
NSUInteger numberOfMatches = [regex numberOfMatchesInString:haystack
options:0 range:stringRange];
NSLog(@"Number of matches for '%@' in '%@': %u", strPattern, haystack, numberOfMatches);
arTextCheckingResults = [regex matchesInString:haystack options:NSRegularExpressionCaseInsensitive range:stringRange];
for (NSTextCheckingResult *ntcr in arTextCheckingResults) {
NSRange matchRange = [ntcr rangeAtIndex:1];
NSString *match = [haystack substringWithRange:matchRange];
NSLog(@"Found string '%@'", match);
}
}
Вывод NSLog:
Найдена строка «слова»
Комментарии:
1. Зачем использовать NSRegularExpressionSearch в следующих строках? NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:Параметры strPattern:Ошибка поиска NSRegularExpressionSearch:amp;ошибка]; Влияет ли это на вызов следующего? arTextCheckingResults = [регулярное выражение соответствует строке:параметры стога сена:NSRegularExpressionCaseInsensitive диапазон:stringRange];
2.
regex
является регулярным выражением и используется для созданияarTextCheckingResults
.3. да, но NSRegularExpressionSearch не является типом NSRegularExpressionOptions, и ни одно из перечислений inNSRegularExpressionOptions не является NSRegularExpressionSearch .