objective c - Los grupos de captura no funcionan en NSRegularExpression
objective-c regex (5)
¿Por qué este código solo muestra toda la coincidencia de expresiones regulares en lugar del grupo de captura?
Entrada
@"A long string containing Name:</td><td>A name here</td> amongst other things"
Salida esperada
A name here
Salida real
Name:</td><td>A name here</td>
Código
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);
}
Código tomado de los documentos de Apple. Sé que hay otras bibliotecas para hacer esto, pero quiero seguir con lo que está integrado en esta tarea.
Accederá al primer rango de grupo usando:
for (NSTextCheckingResult *match in matches) {
//NSRange matchRange = [match range];
NSRange matchRange = [match rangeAtIndex:1];
NSString *matchString = [htmlString substringWithRange:matchRange];
NSLog(@"%@", matchString);
}
En 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)
}
HTML no es un lenguaje normal y no se puede analizar correctamente con expresiones regulares. Aquí hay una respuesta SO clásica que explica esta falta de suposición de programador común.
No analice HTML con expresiones regulares o NSScanner. Por ese camino yace la locura.
Esto se ha preguntado muchas veces en SO.
Los datos que selecciono son tan simples como
<td>Name: A name</td>
y creo que es lo suficientemente simple como para usar expresiones regulares en lugar de incluir un analizador de HTML completo en el proyecto.
Depende de usted y soy un firme defensor de que "el primero en llegar al mercado tiene una gran ventaja".
La diferencia es que con un analizador de HTML adecuado, está considerando la estructura del documento. Al usar expresiones regulares, confía en que el documento nunca cambiará el formato de manera que, sintácticamente, sea perfectamente válido.
Es decir, ¿qué ocurre si la entrada es <td class="name">Name: A name</td>
? Su analizador de expresiones regulares simplemente rompió la entrada que es a la vez HTML válido y, desde una perspectiva de contenido de etiqueta, idéntica a la entrada original.
O simplemente usa
[htmlString firstMatchedGroupWithRegex:@"Name:</td>.*/">(.*)</td>"]
de esta categoría https://github.com/damienromito/NSString-Matcher