2010-10-18 24 views
8

Tôi có một dự án C# tôi dự định chuyển đến Objective-C. Từ những gì tôi hiểu về Obj-C, có vẻ như có nhiều tùy chọn Regex khó hiểu nhưng tôi không thể thấy bất cứ điều gì về cách thay thế bằng gọi lại.Có regex Objective-c thay thế bằng callback/C# MatchEvaluator tương đương không?

Tôi đang tìm thứ gì đó tương đương với đại biểu C# MatchEvaluator hoặc preg_replace_callback của PHP. Ví dụ về những gì tôi muốn làm trong C# là -

// change input so each word is followed a number showing how many letters it has 

string inputString = "Hello, how are you today ?"; 
Regex theRegex = new Regex(@"\w+"); 

string outputString = theRegex.Replace(inputString, delegate (Match thisMatch){ 
    return thisMatch.Value + thisMatch.Value.Length; 
}); 

// outputString is now 'Hello5, how3 are3 you3 today5 ?' 

Làm cách nào tôi có thể thực hiện điều này trong Mục tiêu-C? Trong tình hình thực tế của tôi, Regex có cả hai xác nhận lookahead và lookbehind trong nó mặc dù, vì vậy bất kỳ thay thế liên quan đến việc tìm kiếm các chuỗi trước và sau đó làm một loạt các chuỗi thay thế thẳng sẽ không làm việc không may.

Trả lời

7

Nền tảng có lớp học NSRegularExpression (iOS4 trở lên), có thể hữu ích cho bạn. Từ các tài liệu:

Các phương thức khớp cơ bản cho NSRegularExpression là một khối iterator phương pháp cho phép khách hàng để cung cấp một đối tượng Lô mà sẽ gọi mỗi lần biểu thức chính quy phù hợp với một phần của mục tiêu chuỗi. Có thêm các phương thức tiện lợi để trả lại tất cả các kết quả phù hợp dưới dạng một mảng, tổng số trận đấu là , trận đấu đầu tiên, và phạm vi của trận đấu đầu tiên.

Ví dụ:

NSString *input = @"Hello, how are you today?"; 

// make a copy of the input string. we are going to edit this one as we iterate 
NSMutableString *output = [NSMutableString stringWithString:input]; 

NSError *error = NULL; 
NSRegularExpression *regex = [NSRegularExpression 
           regularExpressionWithPattern:@"\\w+" 
                options:NSRegularExpressionCaseInsensitive 
                 error:&error]; 

// keep track of how many additional characters we've added (1 per iteration) 
__block NSUInteger count = 0; 

[regex enumerateMatchesInString:input 
         options:0 
          range:NSMakeRange(0, [input length]) 
        usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop){ 

    // Note that Blocks in Objective C are basically closures 
    // so they will keep a constant copy of variables that were in scope 
    // when the block was declared 
    // unless you prefix the variable with the __block qualifier 

    // match.range is a C struct 
    // match.range.location is the character offset of the match 
    // match.range.length is the length of the match   

    NSString *matchedword = [input substringWithRange:match.range]; 

    // the matched word with the length appended 
    NSString *new = [matchedword stringByAppendingFormat:@"%d", [matchedword length]]; 

    // every iteration, the output string is getting longer 
    // so we need to adjust the range that we are editing 
    NSRange newrange = NSMakeRange(match.range.location+count, match.range.length); 
    [output replaceCharactersInRange:newrange withString:new]; 

    count++; 
}]; 
NSLog(@"%@", output); //output: Hello5, how3 are3 you3 today5? 
3

tôi đổi mã atshum của để làm cho nó linh hoạt hơn một chút:

__block int prevEndPosition = 0; 
[regex enumerateMatchesInString:text 
         options:0 
          range:NSMakeRange(0, [text length]) 
        usingBlock:^(NSTextCheckingResult *match, NSMatchingFlags flags, BOOL *stop) 
{ 
    NSRange r = {.location = prevEndPosition, .length = match.range.location - prevEndPosition}; 

    // Copy everything without modification between previous replacement and new one 
    [output appendString:[text substringWithRange:r]]; 
    // Append string to be replaced 
    [output appendString:@"REPLACED"]; 

    prevEndPosition = match.range.location + match.range.length; 
}]; 

// Finalize string end 
NSRange r = {.location = prevEndPosition, .length = [text length] - prevEndPosition}; 
[output appendString:[text substringWithRange:r]]; 

Dường như làm việc cho bây giờ (có lẽ cần một thử nghiệm chút)

Các vấn đề liên quan