なぜこのコードはキャプチャグループではなく正規表現全体を吐き出すだけなのですか?
入力
@"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 docsから取得したコード。これを行う他のライブラリがあることは知っていますが、このタスクに組み込まれているものを使い続けたいと思っています。
次のコマンドを使用して、最初のグループ範囲にアクセスします。
for (NSTextCheckingResult *match in matches) {
//NSRange matchRange = [match range];
NSRange matchRange = [match rangeAtIndex:1];
NSString *matchString = [htmlString substringWithRange:matchRange];
NSLog(@"%@", matchString);
}
正規表現やNSScannerでHTMLを解析しないでください。その道の下には狂気があります。
これはSOで何度も尋ねられました。
私が選択しているデータは
<td>Name: A name</td>
と同じくらいシンプルで、プロジェクトに完全なHTMLパーサーを含めるのではなく、正規表現を使用するだけで十分だと思います。
あなたと私は、「最初に市場に投入することには大きなアドバンテージがある」と強く支持しています。
違いは、適切なHTMLパーサーを使用して、ドキュメントの構造を検討していることです。正規表現を使用すると、構文が変更されない限り完全に有効な方法で、ドキュメントが形式を変更しないことに依存します。
つまり入力が<td class="name">Name: A name</td>
の場合はどうなりますか?正規表現パーサーは、有効なHTMLであり、タグコンテンツの観点からは元の入力と同じである入力で壊れました。
HTMLは通常の言語ではないため、正規表現を使用して適切に解析できません。 ここに古典的なSO答え があり、この一般的なプログラマの誤解を説明しています。
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)
}