Created
January 18, 2019 04:08
-
-
Save rickytan/a2906fc6ecc882f4788f853591b67574 to your computer and use it in GitHub Desktop.
NSString regular expression replace
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@interface NSString (RegExp) | |
#pragma clang diagnostic push | |
#pragma clang diagnostic ignored "-Wstrict-prototypes" | |
- (NSString *)reg_replace:(NSRegularExpression *)regexp withBlock:(NSString *(NS_NOESCAPE ^)())block; | |
- (NSString *)reg_replacePattern:(NSString *)pattern withBlock:(NSString *(NS_NOESCAPE ^)())block; | |
#pragma clang diagnostic pop | |
@end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#import "NSString+RegExp.h" | |
FOUNDATION_EXTERN bool _Block_has_signature(id); | |
FOUNDATION_EXTERN const char * _Block_signature(id); | |
@implementation NSString (RegExp) | |
#pragma clang diagnostic push | |
#pragma clang diagnostic ignored "-Wstrict-prototypes" | |
- (NSString *)reg_replacePattern:(NSString *)pattern withBlock:(NSString *(NS_NOESCAPE ^)())block | |
{ | |
return [self reg_replace:[NSRegularExpression regularExpressionWithPattern:pattern | |
options:0 | |
error:NULL] | |
withBlock:block]; | |
} | |
- (NSString *)reg_replace:(NSRegularExpression *)regexp withBlock:(NSString *(NS_NOESCAPE ^)())block | |
#pragma clang diagnostic pop | |
{ | |
NSParameterAssert(regexp); | |
NSParameterAssert(block); | |
NSParameterAssert(_Block_has_signature(block)); | |
__block NSMutableString *newString = [NSMutableString stringWithCapacity:self.length]; | |
__block NSUInteger offset = 0; | |
[regexp enumerateMatchesInString:self | |
options:0 | |
range:NSMakeRange(0, self.length) | |
usingBlock:^(NSTextCheckingResult * _Nullable result, NSMatchingFlags flags, BOOL * _Nonnull stop) { | |
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:[NSMethodSignature signatureWithObjCTypes:_Block_signature(block)]]; | |
NSUInteger numberOfArguments = invocation.methodSignature.numberOfArguments; | |
[invocation setTarget:[block copy]]; | |
__autoreleasing NSString *string = self; | |
[invocation setArgument:&string atIndex:1]; | |
NSRange range = result.range; | |
[invocation setArgument:&range atIndex:2]; | |
string = [self substringWithRange:range]; | |
[invocation setArgument:&string atIndex:3]; | |
NSUInteger count = MIN([result numberOfRanges], numberOfArguments - 3); | |
for (NSUInteger i = 1; i < count; ++i) { | |
NSRange range = [result rangeAtIndex:i]; | |
NSString *substr = [self substringWithRange:range]; | |
[invocation setArgument:&substr atIndex:i + 3]; | |
} | |
[invocation invoke]; | |
[invocation getReturnValue:&string]; | |
[newString appendString:[self substringWithRange:NSMakeRange(offset, range.location - offset)]]; | |
[newString appendString:string]; | |
offset = range.location + range.length; | |
}]; | |
[newString appendString:[self substringWithRange:NSMakeRange(offset, self.length - offset)]]; | |
return newString; | |
} | |
@end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment