44

为什么这段代码只吐出整个正则表达式匹配而不是捕获组?

输入

@"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 文档。我知道还有其他库可以做到这一点,但我想坚持这项任务的内置内容。

4

4 回答 4

74

您将使用以下方式访问第一个组范围:

for (NSTextCheckingResult *match in matches) {
    //NSRange matchRange = [match range];
    NSRange matchRange = [match rangeAtIndex:1];
    NSString *matchString = [htmlString substringWithRange:matchRange];
    NSLog(@"%@", matchString);
}
于 2011-07-25T22:04:17.557 回答
11

不要使用正则表达式或 NSScanner 解析 HTML。沿着这条路走下去就是疯狂。

这已在 SO 上被多次询问。

在 iPhone 上解析 HTML

我挑选的数据很简单<td>Name: A name</td>,我认为它足够简单,只需使用正则表达式,而不是在项目中包含一个完整的 HTML 解析器。

取决于你我是“先到市场有巨大优势”的坚定拥护者。

不同之处在于,使用适当的 HTML 解析器,您正在考虑文档的结构。使用正则表达式,您依赖于文档永远不会以语法上完全有效的方式更改格式。

即如果输入是<td class="name">Name: A name</td>什么?您的正则表达式解析器刚刚破坏了有效的 HTML 输入,并且从标签内容的角度来看,与原始输入相同。

于 2011-07-25T22:03:27.947 回答
4

在 swift3

//: 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)
}
于 2017-02-07T07:12:51.293 回答
3

HTML 不是常规语言,无法使用正则表达式正确解析。这是一个经典的 SO 答案,解释了这种常见的程序员误解。

于 2011-07-28T16:01:55.953 回答