I think you should use this regular expression pattern "\\[.*?]"
then you get three matches
['[abc]', '[test]', '[end]']
then can just get the range of the third match (check that you have at least three)
NSMutableString* stringVal= [NSMutableString stringWithString:@"[abc][test][end]"];
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"\\[.*?]" options:0 error:NULL];
NSArray *matches = [regex matchesInString:stringVal options:0 range:NSMakeRange(0, [stringVal length])];
NSTextCheckingResult* match = matches[2];
NSMutableString* substring = [[stringVal substringToIndex:match.range.location] mutableCopy];