2012-02-09 3 views
2

Есть ли способ написать шаблон регулярного выражения, который будет создавать одну или две группы на основе входного текста. (То есть)Регулярное выражение, определяющее необязательные группы захвата?

// ONE 
NSString *pattern = @""; ([0-9]+).([0-9]+) 
NSString *inputText = @"ThisIs MyTest72.56String"; 
// OUTPUT match = 72.56, group1 = 72, group2 = 56 

То, что я пытаюсь получить это:

// TWO 
NSString *pattern = @""; ([0-9]+).([0-9]+) 
NSString *inputText = @"ThisIs MyTest72String"; 
// OUTPUT match = 72, group1 = 72, group2 = Empty 

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

То, что я после того, как есть :

Text = "ThisIs MyTest72String" 
Match = 72 
Group1 = 72 
Group2 = Empty 

Text = "ThisIs MyTest72.56String" 
Match = 72.56 
Group1 = 72 
Group2 = 56 

EDIT:

Такие работы, хотя я бы хотел избавиться от «S» в начальном матче.

Pattern = ([0-9]+).([0-9]*) 
Text = "ThisIs MyTest72String" 
Match = 72S 
Group1 = 72 //RangeAtIndex:1 {13,2} 
Group2 = Empty //RangeAtIndex:2 {16,0} 

Text = "ThisIs MyTest72.56String" 
Match = 72.56 
Group1 = 72 
Group2 = 56 

Это близко, но в случае «пустой» (группа_2) Я ожидал rangeAtIndex: 2 равным NSNotFound. Документы говорят, что «Диапазон {NSNotFound, 0} возвращается, если одна из групп захвата не участвовала в этом конкретном матче« ли пустая группа не считается «Не участвует»?

ответ

1

Это дает вам то, что вы хотите?

([0-9]+)(?:\.([0-9]+))? 

Я бежал десятичное место (которое не было, не зная, если это необходимо в целевом языке) и сгруппировано десятичный и все после него, как опция, не захваченной группа.

Необходимо просто проверить наличие второй группы.

+0

Спасибо рррр, я новичок в регулярных выражениях, но я вижу, Что король нет. Один последний вопрос: «Трейлинг»? похоже, позволяет первой группе соответствовать сама по себе, можете ли вы объяснить, что именно она делает? – fuzzygoat

+0

Это квантификатор, который делает предыдущий элемент в регулярном выражении (в данном случае всей не захваченной группе) необязательным, чтобы он мог представлять 0 или 1 раз. – rrrr

+0

Понял, спасибо. – fuzzygoat

1

Используйте этот шаблон:

pattern = @"([0-9]+)\.([0-9]+)?"; 

, а затем в NSTextCheckingResult проверки, если место диапазон группа NSNotFound.

Пример кода:

NSString *pattern = @"([0-9]+).([0-9]+)?"; 
NSString *string = @"ThisIs MyTest72.56String"; 
//NSString *string = @"ThisIs MyTest72.XXString"; 

NSRegularExpression *regex = [NSRegularExpression 
           regularExpressionWithPattern:pattern 
           options:NSRegularExpressionCaseInsensitive 
           error:nil]; 

NSTextCheckingResult *match = [regex firstMatchInString:string options:0 range:NSMakeRange(0, string.length)]; 

for (int groupNumber=1; groupNumber<match.numberOfRanges; groupNumber+=1) { 
    NSRange groupRange = [match rangeAtIndex:groupNumber]; 
    if (groupRange.location != NSNotFound) 
     NSLog(@"match %d: '%@'", groupNumber, [string substringWithRange:groupRange]); 
    else 
     NSLog(@"match %d: '%@'", groupNumber, @""); 
} 

NSLog выход:

матч 1: '72'
матч 2: '56'
Со вторым рисунком "матч 2: ''".

+0

Очень ценится, есть ли способ остановить начальное совпадение, включая «S» при использовании вашего шаблона в «ThisIs MyTest73String»? – fuzzygoat

+0

Мой ответ уже учитывает это, ваша проблема состоит в том, что десятичная дробь фактически соответствует любому символу, как это должно быть в регулярных выражениях. – rrrr

+0

А я пропустил это, так что (\.) создает новую группу, которая включает в себя "." и (?: \.) удаляет эту группу из совпадения. Очень ценится ... – fuzzygoat

1

Как об этом:

NSString *inputText = @"ThisIs MyTest72.56String"; 
// Setup an NSError object to catch any failures 
NSError *error = NULL; 
// create the NSRegularExpression object and initialize it with a pattern 
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\d+.\\d+" options:NSRegularExpressionCaseInsensitive error:&error]; 
// create an NSRange object using our regex object for the first match in the string httpline 
NSRange rangeOfFirstMatch = [regex rangeOfFirstMatchInString:inputText options:0 range:NSMakeRange(0, [inputText length])]; 
// check that our NSRange object is not equal to range of NSNotFound 
if (!NSEqualRanges(rangeOfFirstMatch, NSMakeRange(NSNotFound, 0))) { 
    // Since we know that we found a match, get the substring from the parent string by using our NSRange object 
    NSString *substringForFirstMatch = [inputText substringWithRange:rangeOfFirstMatch]; 
    NSLog(@"Extracted string: %@",substringForFirstMatch); // Extracted string: 72.56 

regex = [NSRegularExpression regularExpressionWithPattern:@"\\d+" options:NSRegularExpressionCaseInsensitive error:&error]; 
NSArray *matches = [regex matchesInString:substringForFirstMatch options:0 range:NSMakeRange(0, [substringForFirstMatch length])]; 
for (NSTextCheckingResult *match in matches) { 
    NSString *matchString = [substringForFirstMatch substringWithRange:[match range]]; 
    NSLog(@"match string: %@", matchString); 
    // match string: 72 
    // match string: 56 
} 

} 
+0

Это не удается: "ThisIs MyTest72String" " – zaph

Смежные вопросы