51

PHPでテストするとこの正規表現が機能しますが、Objective Cでは機能しません:

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

エスケープ文字をエスケープしようとしましたが、それも役に立ちません。他のキャラクターをエスケープする必要がありますか?

これはObjective 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);
}

- アップデート -

この正規表現は (PHP では) 値が "domain-name" と "tld.tld2" の配列を返しますが、Objective C では "domain-name.tld.tld2" という 1 つの値しか取得しません。

-- 更新 2 --

この正規表現は、文字列から「ドメイン名」と「TLD」を抽出します。

  • domain.com = (ドメイン、com)
  • domain.co.uk = (ドメイン, co.uk)
  • -test-domain.co.u = (テスト ドメイン, co)
  • -test-domain.co.uk- = (テストドメイン, co.uk)
  • -test-domain.co.uk = (テストドメイン, co)
  • -test-domain.co-m = (テストドメイン)
  • -test-domain-.co.uk = (テストドメイン)

有効なドメイン名 ('-' で開始または終了せず、2 ~ 63 文字の長さ) と、TLD の部分が有効な場合は最大 2 つの部分 (文字と数字のみを含む少なくとも 2 文字の長さ) を取ります。

この説明がお役に立てば幸いです。

4

2 に答える 2

83

ANSTextCheckingResultには、インデックス付けによって取得された複数のアイテムがあります。

[match rangeAtIndex:0];完全一致です。
[match rangeAtIndex:1];(存在する場合) は、最初のキャプチャ グループの一致です。

次のようなものを使用できます。

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 出力:

一致: ドメイン名.tld.tld2
ドメイン名
tld.tld2

一致範囲が有効であることをテストしてください。

この場合、より簡単に:

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

スウィフト 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)
}

印刷出力:

match: ドメイン名.tld.tld2
matchText1: ドメイン名
matchText2: tld.tld2

この場合、より簡単に:

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

印刷出力:

matchText1: ドメイン名
matchText2: tld.tld2

于 2012-02-14T12:24:46.623 に答える
17

Apple のドキュメントによると、これらの文字をリテラルとして扱うには (\ を使用して) 引用符で囲む必要があります。

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

また、達成しようとしていることを説明していただけると助かります。テストフィクスチャはありますか?

于 2012-02-14T11:52:46.790 に答える