Cómo escribir expresiones regulares en el Objetivo C (NSRegularExpression)?

Tengo esta expresión regular funcionando cuando la pruebo en PHP pero no funciona en el Objetivo C:

(?:www\.)?((?!-)[a-zA-Z0-9-]{2,63}(?<!-))\.?((?:[a-zA-Z0-9]{2,})?(?:\.[a-zA-Z0-9]{2,})?) 

Traté de escaping de los personajes de escape, pero eso tampoco ayuda. ¿Debería escaping a cualquier otro personaje?

Este es mi código en el Objetivo C:

 NSMutableString *searchedString = [NSMutableString stringWithString:@"domain-name.tld.tld2"]; NSError* error = nil; NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:@"(?:www\\.)?((?!-)[a-zA-Z0-9-]{2,63}(?<!-))\\.?((?:[a-zA-Z0-9]{2,})?(?:\\.[a-zA-Z0-9]{2,})?)" options:0 error:&error]; NSArray* matches = [regex matchesInString:searchedString options:0 range:NSMakeRange(0, [searchedString length])]; for ( NSTextCheckingResult* match in matches ) { NSString* matchText = [searchedString substringWithRange:[match range]]; NSLog(@"match: %@", matchText); } 

– ACTUALIZACIÓN –

Esta expresión regular devuelve (en PHP) la matriz con los valores "nombre-dominio" y "tld.tld2" pero en Objective C obtengo solo un valor: "domain-name.tld.tld2"

– ACTUALIZACIÓN 2 –

Esta expresión regular extrae 'nombre de dominio' y 'TLD' de la cadena:

  • domain.com = (dominio, com)
  • domain.co.uk = (dominio, co.uk)
  • -test-domain.co.u = (test-domain, co)
  • -test-domain.co.uk- = (test-domain, co.uk)
  • -test-domain.co.uk = (test-domain, co)
  • -test-domain.co-m = (dominio de testing)
  • -test-domain-.co.uk = (dominio de testing)

toma el nombre de dominio válido (que no comienza ni termina con '-' y entre 2 y 63 caracteres de longitud), y hasta dos partes de un TLD si las partes son válidas (al less dos caracteres que contienen solo letras y numbers)

Espero que esta explicación ayude.

Un NSTextCheckingResult tiene varios elementos obtenidos al NSTextCheckingResult .

[match rangeAtIndex:0]; es la combinación completa
[match rangeAtIndex:1]; (si existe) es la primera coincidencia del grupo de captura.
etc

Puedes usar algo como esto:

 NSString *searchedString = @"domain-name.tld.tld2"; NSRange searchedRange = NSMakeRange(0, [searchedString length]); NSString *pattern = @"(?:www\\.)?((?!-)[a-zA-Z0-9-]{2,63}(?<!-))\\.?((?:[a-zA-Z0-9]{2,})?(?:\\.[a-zA-Z0-9]{2,})?)"; NSError *error = nil; NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern: pattern options:0 error:&error]; NSArray* matches = [regex matchesInString:searchedString options:0 range: searchedRange]; for (NSTextCheckingResult* match in matches) { NSString* matchText = [searchedString substringWithRange:[match range]]; NSLog(@"match: %@", matchText); NSRange group1 = [match rangeAtIndex:1]; NSRange group2 = [match rangeAtIndex:2]; NSLog(@"group1: %@", [searchedString substringWithRange:group1]); NSLog(@"group2: %@", [searchedString substringWithRange:group2]); } 

Salida NSLog:

coincidencia: domain-name.tld.tld2
nombre de dominio
tld.tld2

Pruebe que los ranges de coincidencia son válidos.

Más simplemente en este caso:

 NSString *searchedString = @"domain-name.tld.tld2"; NSRange searchedRange = NSMakeRange(0, [searchedString length]); NSString *pattern = @"(?:www\\.)?((?!-)[a-zA-Z0-9-]{2,63}(?<!-))\\.?((?:[a-zA-Z0-9]{2,})?(?:\\.[a-zA-Z0-9]{2,})?)"; NSError *error = nil; NSRegularExpression* regex = [NSRegularExpression regularExpressionWithPattern:pattern options:0 error:&error]; NSTextCheckingResult *match = [regex firstMatchInString:searchedString options:0 range: searchedRange]; NSLog(@"group1: %@", [searchedString substringWithRange:[match rangeAtIndex:1]]); NSLog(@"group2: %@", [searchedString substringWithRange:[match rangeAtIndex:2]]); 

Swift 3.0:

 let searchedString = "domain-name.tld.tld2" let nsSearchedString = searchedString as NSString let searchedRange = NSMakeRange(0, searchedString.characters.count) let pattern = "(?:www\\.)?((?!-)[a-zA-Z0-9-]{2,63}(?<!-))\\.?((?:[a-zA-Z0-9]{2,})?(?:\\.[a-zA-Z0-9]{2,})?)" do { let regex = try NSRegularExpression(pattern:pattern, options: []) let matches = regex.matches(in:searchedString, options:[], range:searchedRange) for match in matches { let matchText = nsSearchedString.substring(with:match.range); print("match: \(matchText)"); let group1 : NSRange = match.rangeAt(1) let matchText1 = nsSearchedString.substring(with: group1) print("matchText1: \(matchText1)") let group2 = match.rangeAt(2) let matchText2 = nsSearchedString.substring(with: group2) print("matchText2: \(matchText2)") } } catch let error as NSError { print(error.localizedDescription) } 

salida de printing:

coincidencia: domain-name.tld.tld2
matchText1: nombre-dominio
matchText2: tld.tld2

Más simplemente en este caso:

 do { let regex = try NSRegularExpression(pattern:pattern, options: []) let match = regex.firstMatch(in:searchedString, options:[], range:searchedRange) let matchText1 = nsSearchedString.substring(with: match!.rangeAt(1)) print("matchText1: \(matchText1)") let matchText2 = nsSearchedString.substring(with: match!.rangeAt(2)) print("matchText2: \(matchText2)") } catch let error as NSError { print(error.localizedDescription) } 

salida de printing:

matchText1: nombre-dominio
matchText2: tld.tld2

De acuerdo con la documentation de Apple , estos caracteres deben ser citados (usando \) para ser tratados como literales:

 * ? + [ ( ) { } ^ $ | \ . / 

También ayudaría si pudiera explicar lo que está tratando de lograr. ¿Tienes algún accesorio de testing?