是否有一个Objective-c正则表达式替换为callback/C#MatchEvaluator等效?

mik*_*kel 8 regex replace objective-c callback nsregularexpression

我有一个C#项目,我打算移植到Objective-C.根据我对Obj-C的理解,看起来有一些令人困惑的Regex选项,但我看不到任何关于用回调替换的方法.

我正在寻找的东西相当于C#MatchEvaluator委托或PHP的preg_replace_callback.我想在C#中做的一个例子是 -

// 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 ?'
Run Code Online (Sandbox Code Playgroud)

我怎么能在Objective-C中做到这一点?在我的实际情况中,正则表达式中有前瞻性和后瞻性断言,因此任何涉及提前查找字符串然后进行一系列直接字符串替换的替代方案都将无法正常工作.

小智 7

Foundation有一个NSRegularExpression类(iOS4及更高版本),可能对您有用.来自文档:

NSRegularExpression的基本匹配方法是Block迭代器方法,它允许客户端提供Block对象,每当正则表达式匹配目标字符串的一部分时将调用该对象.还有其他方便的方法可以将所有匹配作为数组,匹配总数,第一个匹配和第一个匹配的范围返回.

例如:

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?
Run Code Online (Sandbox Code Playgroud)