Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/regex/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Regex 如何使用NSRegularExpression';s replacementStringForResult:指令:偏移量:模板:_Regex_Cocoa Touch - Fatal编程技术网

Regex 如何使用NSRegularExpression';s replacementStringForResult:指令:偏移量:模板:

Regex 如何使用NSRegularExpression';s replacementStringForResult:指令:偏移量:模板:,regex,cocoa-touch,Regex,Cocoa Touch,我有一系列要与正则表达式匹配的字符,并根据它们是什么用特定字符串替换它们 例如: In=>“这是我要替换1、2和3的输入字符串” Out=>“这是我要替换1、2和3的输入字符串” 目前,我使用空格作为分隔符拆分字符串,并单独解析每个字符串,以增量方式重新生成字符串。我觉得这很难看,缺乏想象力,而且有点慢 根据苹果的文档,我应该能够使用replacementStringForResult:inString:offset:template:方法来实现这一点。然而,我似乎不明白如何正确使用它。你应该使

我有一系列要与正则表达式匹配的字符,并根据它们是什么用特定字符串替换它们

例如:

In=>“这是我要替换1、2和3的输入字符串”

Out=>“这是我要替换1、2和3的输入字符串”

目前,我使用空格作为分隔符拆分字符串,并单独解析每个字符串,以增量方式重新生成字符串。我觉得这很难看,缺乏想象力,而且有点慢

根据苹果的文档,我应该能够使用
replacementStringForResult:inString:offset:template:
方法来实现这一点。然而,我似乎不明白如何正确使用它。

你应该使用它

- (NSString *)stringByReplacingMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range withTemplate:(NSString *)template


字符串为“这是我要替换1 2和3的输入字符串”,模板为“1”、“2”或“3”。

您可以在
for in
循环中使用
方法,使用
匹配安装:选项:范围:
,它返回一个匹配数组作为
NSTextCheckingResult
s:

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

我建议这样做,时间要短得多,占用的内存也少:

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
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
下面是如何使用它来解决最初的问题:

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

对于同一个问题,我需要一个更通用的解决方案,因此我改进了Dano对这种方法的回答,下面解释了一个示例用法:

- (NSMutableString *)replaceSubstringsInString:(NSString*)string
                                    usingRegex:(NSString*)searchRegex
                              withReplacements:(NSDictionary*)replacements {

    NSMutableString *newString = [string mutableCopy];
    __block NSInteger offset = 0;

    NSError *error = NULL;

    NSRegularExpression *regex = [NSRegularExpression
                                  regularExpressionWithPattern:searchRegex
                                  options:0
                                  error:&error];

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

                             NSRange resultRange = [match range];
                             resultRange.location += offset;

                             NSString *substring = [string substringWithRange:match.range];

                             __block NSString* replacement;

                             [replacements enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {

                                 if ([key isEqualToString:substring]) {
                                     replacement = obj;
                                 }

                             }];

                             [newString replaceCharactersInRange:resultRange withString:replacement];

                             offset += ([replacement length] - resultRange.length);
                         }];

    return newString;
}
用法:

NSString *string = @"This is the input string where i want to replace 1 2 & 3";
NSString *searchRegex = @"\\b[1-3]\\b";
NSDictionary *replacements = @{@"1":@"ONE",@"2":@"TWO",@"3":@"THREE"};

NSMutableString *result = [self replaceSubstringsInString:string
                                               usingRegex:searchRegex
                                         withReplacements:replacements];
 //   This is the input string where i want to replace ONE TWO & THREE
说明: 只需传入
字符串
即可搜索匹配的子字符串,以及所需的
regexSearch
模式和
replacements
字典,其中包含字符串对,其中
是要替换的子字符串,而
对象
包含所需的替换字符串

输出:

NSString *string = @"This is the input string where i want to replace 1 2 & 3";
NSString *searchRegex = @"\\b[1-3]\\b";
NSDictionary *replacements = @{@"1":@"ONE",@"2":@"TWO",@"3":@"THREE"};

NSMutableString *result = [self replaceSubstringsInString:string
                                               usingRegex:searchRegex
                                         withReplacements:replacements];
 //   This is the input string where i want to replace ONE TWO & THREE

我在寻找类似的东西,但不喜欢这里的大多数答案,所以我写了一些受PHP如何进行字符串替换启发的东西:

@implementation NSString (preg_replace)

- (instancetype)stringByReplacingMatchesFromRegularExpression:(NSRegularExpression *)regularExpression replacementBlock:(NSString * (^)(NSArray *matches))replacementBlock
{
    NSMutableString *finalString = self.mutableCopy;
    NSUInteger offset = 0;

    for (NSTextCheckingResult *match in [regularExpression matchesInString:self options:0 range:NSMakeRange(0, self.length)]) {
        NSMutableArray *matches = [NSMutableArray array];
        for (NSUInteger index = 0; index < match.numberOfRanges; ++index) {
            [matches addObject:[self substringWithRange:[match rangeAtIndex:index]]];
        }
        NSString *replacementString = replacementBlock(matches.copy);

        [finalString replaceCharactersInRange:NSMakeRange(match.range.location + offset, match.range.length) withString:replacementString];
        offset += replacementString.length - match.range.length;
    }

    return finalString;
}

@end

谢谢马库斯!我发现文档中没有明确说明如何正确使用此方法,所以我希望它能有所帮助。将此代码封装在这个NSString类别方法中很好:-(NSString*)gsub:(NSRegularExpression*)regexp with matchTransformation:(NSString*(^)(NSString*元素))block;请注意,当替换字符串比原始字符串短时,此操作不起作用,因为
NSRange
由无符号整数组成,因此如果从较小的数字中减去较大的数字,将不会得到负数,而是一个巨大的正数。循环并跟踪偏移量的想法非常有效!在我的例子中,我没有使用[NSRegularExpression replacementStringForResult:…]方法。相反,我只是在修改的结果范围中使用了普通的老[mutableString substringWithRange:resultRange]方法来获取要替换的字符串,并根据需要将其替换为不同的字符串。Dano显示的偏移方法实际上适用于较长和较短的替换字符串。