43 votes

Les groupes de capture ne fonctionnent pas dans NSRegularExpression

Pourquoi ce code ne renvoie-t-il que l'ensemble de la correspondance regex au lieu du groupe de capture ?

Entrée

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

Résultats attendus

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 la documentation d'Apple. Je sais qu'il existe d'autres bibliothèques pour faire cela mais je veux m'en tenir à ce qui est intégré pour cette tâche.

74voto

Vous accéderez à la première gamme de groupes en utilisant :

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

11voto

bbum Points 124887

N'analysez pas le HTML avec des expressions régulières ou NSScanner. Ce chemin mène à la folie.

Cette question a été posée à de nombreuses reprises sur SO.

analyser le HTML sur l'iPhone

Les données que j'extrais sont aussi simples que les suivantes <td>Name: A name</td> et i Je pense que c'est assez simple pour ju d'inclure un analyseur HTML complet dans le projet.

C'est à vous de voir, et je suis un fervent défenseur de l'idée que "le premier sur le marché a un avantage énorme".

La différence est qu'avec un analyseur HTML correct, vous tenez compte de la structure du document. En utilisant des expressions régulières, vous vous fiez au fait que le document ne change jamais de format d'une manière qui est par ailleurs syntaxiquement parfaitement valide.

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

3voto

Toro Points 4827

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

3voto

Le HTML n'est pas un langage régulier et ne peut pas être analysé correctement à l'aide d'expressions régulières. Voici une réponse classique de l'OS expliquant cette erreur de jugement courante chez les programmeurs.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X