我想要与正则表达式匹配的一系列字符,并根据它们的具体字符串替换它们。
示例:
In => “这是我要替换1 2& 3”的输入字符串
Out => “这是输入字符串,我想替换ONE TWO& THREE”
我目前通过使用空格作为分隔符拆分字符串,并逐个解析每个字符串,逐步重建字符串来完成此操作。我觉得这很难看,缺乏想象力,而且有点慢。
根据Apple文档,我应该可以使用replacementStringForResult:inString:offset:template:
方法执行此操作。但是我似乎无法理解如何正确使用它。
答案 0 :(得分:35)
您可以使用for in
在matchesInString:options:range:
循环中使用该方法,该NSTextCheckingResult
会返回一个匹配数组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
s:
{{1}}
答案 1 :(得分: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
<强> 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;
}
}];
答案 2 :(得分:2)
你应该使用
- (NSString *)stringByReplacingMatchesInString:(NSString *)string options:(NSMatchingOptions)options range:(NSRange)range withTemplate:(NSString *)template
或
- (NSUInteger)replaceMatchesInString:(NSMutableString *)string options:(NSMatchingOptions)options range:(NSRange)range withTemplate:(NSString *)template
字符串为“这是输入字符串,我想要替换1 2&amp; 3”,模板是“ONE”,“TWO “或”THREE“。
答案 3 :(得分:1)
我需要一个针对同一问题的更通用的解决方案,所以我对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];
<强>说明:强>
您只需要传递string
来搜索匹配的子字符串,以及所需的regexSearch
模式和replacements
字典,其中包含字符串对key
是要替换的子字符串,object
是所需的替换字符串。
<强>输出:强>
// This is the input string where i want to replace ONE TWO & THREE
答案 4 :(得分:0)
我正在寻找类似的东西,但不喜欢这里的大多数答案,所以我写了一些灵感来自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
使用它:
NSRegularExpression *expression = [[NSRegularExpression alloc] initWithPattern:@"[0-9A-F]{2}" options:0 error:nil];
NSString *string = @"AB-DE-EF";
NSString *result = [string stringByReplacingMatchesFromRegularExpression:expression replacementBlock:^NSString *(NSArray *matches) {
return [NSString stringWithFormat:@"(%@)", [matches[0] lowercaseString]];
}];
NSLog(@"Result = %@", result); // "(ab)-(de)-(ef)"
答案 5 :(得分:-2)
我推荐这个,更短,并使用一点内存: Another solution