web-dev-qa-db-fra.com

Les groupes de capture ne fonctionnent pas dans NSRegularExpression

Pourquoi ce code crache-t-il uniquement toute la correspondance d'expression régulière au lieu du groupe de capture?

entrée

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

Sortie attendue

A name here

sortie réelle

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

Code

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);
}

Code tiré de Apple docs. Je sais qu'il existe d'autres bibliothèques pour ce faire, mais je veux m'en tenir à ce qui est intégré pour cette tâche.

42
Maciej Swic

Vous accéderez à la première plage de groupe en utilisant:

for (NSTextCheckingResult *match in matches) {
    //NSRange matchRange = [match range];
    NSRange matchRange = [match rangeAtIndex:1];
    NSString *matchString = [htmlString substringWithRange:matchRange];
    NSLog(@"%@", matchString);
}
71
user756245

Ne pas analyser HTML avec des expressions régulières ou NSScanner. Sur cette voie se trouve la folie.

Cela a été demandé à plusieurs reprises sur SO.

analyse HTML sur l'iPhone

Les données que je choisis sont aussi simples que <td>Name: A name</td> et je pense que c'est assez simple pour simplement utiliser des expressions régulières au lieu d'inclure un analyseur HTML complet dans le projet.

À vous de voir et je suis un ardent défenseur du "premier sur le marché a un énorme avantage".

La différence étant qu'avec un analyseur HTML approprié, vous envisagez la structure du document. À l'aide d'expressions régulières, vous vous fiez au document qui ne change jamais de format de manière syntaxiquement parfaitement valide.

C'est à dire. et si l'entrée était <td class="name">Name: A name</td>? Votre analyseur d'expressions rationnelles vient de se casser sur une entrée à la fois HTML valide et, du point de vue du contenu des balises, identique à l'entrée d'origine.

10
bbum

HTML n'est pas un langage standard et ne peut pas être correctement analysé à l'aide d'expressions régulières. Voici un classique SO expliquant cette erreur de programmation courante.

3
user155959

Dans 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)
}
2
AechoLiu