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