web-dev-qa-db-ger.com

Wie schreibe ich reguläre Ausdrücke in Objective C (NSRegularExpression)?

Ich habe diesen regulären Ausdruck, wenn ich ihn in PHP) teste, aber in Ziel C funktioniert er nicht:

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

Ich habe versucht, den Escape-Zeichen zu entkommen, aber das hilft auch nicht. Soll ich einer anderen Figur entkommen?

Dies ist mein Code in Ziel 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);
}

- UPDATE -

Diese Regex gibt (in PHP) das Array mit den Werten "domain-name" und "tld.tld2" zurück, aber in Objective C erhalte ich nur einen Wert: "domain-name.tld.tld2"

- UPDATE 2 -

Dieser reguläre Ausdruck extrahiert 'Domainname' und 'TLD' aus der Zeichenfolge:

  • domain.com = (domain, com)
  • domain.co.uk = (domain, co.uk)
  • -test-domain.co.u = (test-domain, co)
  • -test-domain.co.uk- = (test-domain, co.uk)
  • -test-domain.co.u-k = (test-domain, co)
  • -test-domain.co-m = (Testdomain)
  • -testdomain.de = (Testdomain)

es wird der gültige Domänenname verwendet (der nicht mit '-' beginnt oder endet und zwischen 2 und 63 Zeichen lang ist) und bis zu zwei Teile einer TLD, wenn die Teile gültig sind (mindestens zwei Zeichen, die nur Buchstaben und Zahlen enthalten).

Hoffe, diese Erklärung hilft.

48
budidino

Ein NSTextCheckingResult enthält mehrere Elemente, die durch Indizieren erhalten wurden.

[match rangeAtIndex:0]; ist die vollständige Übereinstimmung.
[match rangeAtIndex:1]; (falls vorhanden) ist die erste Übereinstimmung der Erfassungsgruppe.
etc.

Sie können so etwas verwenden:

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

NSLog-Ausgabe:

übereinstimmung: domain-name.tld.tld2
Domainname
tld.tld2

Testen Sie, ob die Übereinstimmungsbereiche gültig sind.

Einfacher in diesem Fall:

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

druckausgabe:

übereinstimmung: domain-name.tld.tld2
matchText1: Domainname
matchText2: tld.tld2

Einfacher in diesem Fall:

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

druckausgabe:

matchText1: Domainname
matchText2: tld.tld2

77
zaph

Gemäß Apples Dokumentation müssen diese Zeichen in Anführungszeichen gesetzt werden (mit \), um als Literale behandelt zu werden:

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

Es wäre auch hilfreich, wenn Sie erklären könnten, was Sie erreichen möchten. Hast du irgendwelche Testvorrichtungen?

14
hwaxxer