问题
I have a string like:
?key=123%252Bf-34Fa&name=John
?name=Johon&key=123%252Bf-34Fa
I want to get the value for the key
,I use this NSRegularExpression
(?i)(?<=key=)[.?!&]+[?=&]??
What I think is that the pattern is like matching any character except "&".But the result is always NULL
.
the value of each key can have anything except "&". So How can I create the correct NSRegularExpression? thanks.
回答1:
You shouldn't use a regex for this, specially if you don't know how. Compare:
NSString *string = @"?name=Johon&key=123%252Bf-34Fa";
// NSString *string = @"?key=123%252Bf-34Fa&name=John";
// one way
NSRange range = [string rangeOfString:@"key="];
if (range.location!=NSNotFound){
string = [string substringFromIndex:NSMaxRange(range)];
range = [string rangeOfString:@"&"];
if (range.location!=NSNotFound){
string = [string substringToIndex:range.location];
}
}
// another way
__block NSString *keyValue = nil;
[[string componentsSeparatedByString:@"&"] enumerateObjectsUsingBlock:^(id object, NSUInteger index, BOOL *stop){
NSRange range = [object rangeOfString:@"key="];
if (range.location!=NSNotFound){
keyValue = [object substringFromIndex:range.location+range.length];
*stop = YES;
}
}];
// regex way
NSString *regexStr = @"[\\?&]key=([^&#]*)";
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:regexStr options:0 error:&error];
// enumerate all matches
if ((regex==nil) && (error!=nil)){
NSLog( @"Regex failed for url: %@, error was: %@", string, error);
} else {
[regex enumerateMatchesInString:string
options:0
range:NSMakeRange(0, [string length])
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop){
if (result!=nil){
// iterate ranges
for (int i=0; i<[result numberOfRanges]; i++) {
NSRange range = [result rangeAtIndex:i];
NSLog(@"%ld,%ld group #%d %@", range.location, range.length, i,
(range.length==0 ? @"--" : [string substringWithRange:range]));
}
}
}];
}
回答2:
I know it's been years since the answer was posted, but while the code in Jano's answer is technically correct, calling rangeOfString
multiple time is very inefficient.
The regex is actually quite simple. You can do one of the two following:
key=([^&\s]+) // searches for the key
// matches all characters other than whitespace characters
// and ampersands
([^&?\s]+)=([^&\s]+) // searches for key/value pairs
// key matches all characters other than whitespace characters
// and ampersands and question marks
// value matches all characters other than whitespace characters
// and ampersands
The code in Objective-C using NSRegularExpression
would look like this:
NSString *stringToSearch = @"?name=John&key=123%252Bf-34Fa"
NSError *error;
NSRegularExpression *findKey = [NSRegularExpression regularExpressionWithPattern:@"key=([^&\\s]+)" options:0 error:&error];
if (error) {
// log error
}
NSString *keyValue;
NSTextCheckingResult *match = [findKey firstMatchInString:stringToSearch options:0 range:NSMakeRange(0, stringToSearch.length)];
if (match) {
NSRange keyRange = [match rangeAtIndex:1];
keyValue = [stringToSearch substring:keyRange];
}
or like this:
NSString *stringToSearch = @"?name=John&key=123%252Bf-34Fa"
NSError *error;
NSRegularExpression *findParameters = [NSRegularExpression regularExpressionWithPattern:@"([^&?\\s]+)=([^&\\s]+)" options:0 error:&error];
if (error) {
// log error
}
NSMutableDictionary *keyValuePairs = [[NSMutableDictionary alloc] init];
NSArray *matches = [findParameters matchesInString:stringToSearch options:0 range:NSMakeRange(0, stringToSearch.length)];
for (NSTextCheckingResult *match in matches) {
NSRange keyNameRange = [match rangeAtIndex:1];
NSRange keyValueRange = [match rangeAtIndex:2];
keyValuePairs[[stringToSearch substring:keyNameRange]] = [stringToSearch substring:keyValueRange];
}
Note the double backslash (\\) to escape the backslash when using the regex in actual code.
来源:https://stackoverflow.com/questions/7442549/nsregularexpression