你如何使用NSRegularExpression的replacementStringForResult:inString:offset:template:

Jon*_*han 14 regex cocoa-touch

我有一系列我想要与正则表达式匹配的字符,并根据它们的含义将它们替换为特定的字符串.

例:

In =>"这是我要替换1 2&3的输入字符串"

Out =>"这是我要替换ONE TWO&THREE的输入字符串"

我目前通过使用空格作为分隔符拆分字符串,并分别解析每个字符串,逐步重建字符串来完成此操作.我觉得这很难看,缺乏想象力,而且有点慢.

根据Apple文档,我应该可以使用该replacementStringForResult:inString:offset:template:方法执行此操作.但是我似乎无法理解如何正确使用它.

Dan*_*and 35

你可以在for in循环中使用该方法matchesInString:options:range:,它返回一个匹配数组作为NSTextCheckingResults:

NSError* error = NULL;
NSRegularExpression* regex = [NSRegularExpression 
                              regularExpressionWithPattern:@"\\b[1-3]\\b"
                              options:NSRegularExpressionCaseInsensitive
                              error:&error]; 

NSString* yourString = @"This is the input string where i want to replace 1 2 & 3";

NSMutableString* mutableString = [yourString mutableCopy];
NSInteger offset = 0; // keeps track of range changes in the string
                      // due to replacements.
for (NSTextCheckingResult* result in [regex matchesInString:yourString 
                                                    options:0 
                                                      range:NSMakeRange(0, [yourString length])]) {

    NSRange resultRange = [result range];   
    resultRange.location += offset; // resultRange.location is updated 
                                    // based on the offset updated below

    // implement your own replace functionality using
    // replacementStringForResult:inString:offset:template:
    // note that in the template $0 is replaced by the match
    NSString* match = [regex replacementStringForResult:result 
                                               inString:mutableString 
                                                 offset:offset 
                                               template:@"$0"];
    NSString* replacement;
    if ([match isEqualToString:@"1"]) {
        replacement = @"ONE";
    } else if ([match isEqualToString:@"2"]) {
        replacement = @"TWO";
    } else if ([match isEqualToString:@"3"]) {
        replacement = @"THREE";
    }

    // make the replacement
    [mutableString replaceCharactersInRange:resultRange withString:replacement];

    // update the offset based on the replacement
    offset += ([replacement length] - resultRange.length);
}

NSLog(@"mutableString: %@", mutableString); // mutableString: This is the input string where i want to replace ONE TWO & THREE
Run Code Online (Sandbox Code Playgroud)

  • 很高兴将此代码封装在此NSString类别方法中: - (NSString*)gsub:(NSRegularExpression*)regexp withMatchTransformation:(NSString*(^)(NSString*element))block; (4认同)

Jea*_*ste 7

Dano的答案完美无缺,并且在评论中遵循Pedro的想法,我将代码包装成一个类别,该类别采用了替换部分的块.这非常方便使用.

NSRegularExpression + Replacement.h

@interface NSRegularExpression (Replacement)

- (NSString *)stringByReplacingMatchesInString:(NSString *)string
                                       options:(NSMatchingOptions)options
                                         range:(NSRange)range
                                      template:(NSString *)templ
                       withMatchTransformation: (NSString* (^) (NSString* element))transformation;

@end
Run Code Online (Sandbox Code Playgroud)

NSRegularExpression + Replacement.m

@implementation NSRegularExpression (Replacement)

- (NSString *)stringByReplacingMatchesInString:(NSString *)string
                                       options:(NSMatchingOptions)options
                                         range:(NSRange)range
                                      template:(NSString *)templ
                       withMatchTransformation: (NSString* (^) (NSString* element))transformation
{
    NSMutableString* mutableString = [string mutableCopy];
    NSInteger offset = 0; // keeps track of range changes in the string due to replacements.
    for (NSTextCheckingResult* result in [self matchesInString:string
                                                        options:0
                                                          range:range])
    {
        NSRange resultRange = [result range];
        resultRange.location += offset; // resultRange.location is updated based on the offset updated below

        // implement your own replace functionality using
        // replacementStringForResult:inString:offset:template:
        // note that in the template $0 is replaced by the match
        NSString* match = [self replacementStringForResult:result
                                                   inString:mutableString
                                                     offset:offset
                                                   template:templ];

        // get the replacement from the provided block
        NSString *replacement = transformation(match);

        // make the replacement
        [mutableString replaceCharactersInRange:resultRange withString:replacement];

        // update the offset based on the replacement
        offset += ([replacement length] - resultRange.length);
    }
    return mutableString;
}

@end
Run Code Online (Sandbox Code Playgroud)

以下是您如何使用它来解决最初的问题:

NSString* yourString = @"This is the input string where i want to replace 1 2 & 3";
NSError* error = nil;
NSRegularExpression* regex = [NSRegularExpression
                              regularExpressionWithPattern:@"\\b[1-3]\\b"
                              options:0
                              error:&error];

return [regex stringByReplacingMatchesInString:yourString options:0 range:NSMakeRange(0, [yourString length]) template:@"$0" withMatchTransformation:^NSString *(NSString *match) {
    NSString* replacement;
    if ([match isEqualToString:@"1"]) {
        replacement = @"ONE";
    } else if ([match isEqualToString:@"2"]) {
        replacement = @"TWO";
    } else if ([match isEqualToString:@"3"]) {
        replacement = @"THREE";
    } else {
        return replacement;
    }
}];
Run Code Online (Sandbox Code Playgroud)