Группы захвата не работают в NSRegularExpression - PullRequest
38 голосов
/ 26 июля 2011

Почему этот код только выплевывает все совпадения с регулярным выражением вместо группы захвата?

Input

@"A long string containing Name:</td><td>A name here</td> amongst other things"

Ожидаемый результат

A name here

Фактическая мощность

Name:</td><td>A name here</td>

Код

NSString *htmlString = @"A long string containing Name:</td><td>A name here</td> amongst other things";
NSRegularExpression *nameExpression = [NSRegularExpression regularExpressionWithPattern:@"Name:</td>.*\">(.*)</td>" options:NSRegularExpressionSearch error:nil];

NSArray *matches = [nameExpression matchesInString:htmlString
                                  options:0
                                    range:NSMakeRange(0, [htmlString length])];
for (NSTextCheckingResult *match in matches) {
    NSRange matchRange = [match range];
    NSString *matchString = [htmlString substringWithRange:matchRange];
    NSLog(@"%@", matchString);
}

Код взят из документов Apple. Я знаю, что для этого есть другие библиотеки, но я хочу придерживаться того, что встроено для этой задачи.

Ответы [ 5 ]

66 голосов
/ 26 июля 2011

Вы получите доступ к первому диапазону группы, используя:

for (NSTextCheckingResult *match in matches) {
    //NSRange matchRange = [match range];
    NSRange matchRange = [match rangeAtIndex:1];
    NSString *matchString = [htmlString substringWithRange:matchRange];
    NSLog(@"%@", matchString);
}
10 голосов
/ 26 июля 2011

Не анализируйте HTML с помощью регулярных выражений или NSScanner.На этом пути лежит безумие.

Об этом много раз спрашивали на SO.

анализ HTML на iPhone

Данные, которые я выбираю, так же просты, как <td>Name: A name</td>, и я думаю, что это простодостаточно просто использовать регулярные выражения вместо того, чтобы включать в проект полноценный HTML-парсер.

До вас, и я решительный сторонник того, что «первый на рынке имеет огромное преимущество».

Разница в том, что при правильном парсере HTML вы рассматриваете структуру документа.Используя регулярные выражения, вы полагаетесь на документ, никогда не меняющий формат способами, которые синтаксически иным образом совершенно действительны.

Т.е. что, если ввод был <td class="name">Name: A name</td>?Ваш анализатор регулярных выражений только что прервал ввод, который является действительным HTML и, с точки зрения содержимого тега, идентичен исходному вводу.

3 голосов
/ 28 июля 2011

HTML не является обычным языком и не может быть правильно проанализирован с помощью регулярных выражений. Вот классический SO-ответ , объясняющий это распространенное заблуждение программиста.

2 голосов
/ 07 февраля 2017

В быстром3

//: Playground - noun: a place where people can play

import UIKit

/// Two groups. 1: [A-Z]+, 2: [0-9]+
var pattern = "([A-Z]+)([0-9]+)"

let regex = try NSRegularExpression(pattern: pattern, options:[.caseInsensitive])

let str = "AA01B2C3DD4"
let strLen = str.characters.count
let results = regex.matches(in: str, options: [], range: NSMakeRange(0, strLen))

let nsStr = str as NSString

for a in results {

    let c = a.numberOfRanges 
    print(c)

    let m0 = a.rangeAt(0)  //< Ex: 'AA01'
    let m1 = a.rangeAt(1)  //< Group 1: Alpha chars, ex: 'AA'
    let m2 = a.rangeAt(2)  //< Group 2: Digital numbers, ex: '01'
    // let m3 = a.rangeAt(3) //< Runtime exceptions

    let s = nsStr.substring(with: m2)
    print(s)
}
0 голосов
/ 29 января 2015

Или просто используйте

[htmlString firstMatchedGroupWithRegex:@"Name:</td>.*\">(.*)</td>"]

из этой категории https://github.com/damienromito/NSString-Matcher

...