1

Building an iOS app that needs to display some HTML string in a UIWebView object. I am trying to search, find for a pattern and replace with the proper link to an image. The image links are original something like [pic:brand:123], where pic is always pic , brand can be any alphanumeric, and the 123 is can also be any non-whitespace alphanumeric.

So far I have tried a few including:

NSString *pattern = @"\\[pic:([^\\s:\\]]+):([^\\]])\\]";

But none has worked for so far.

Here is a sample code:

NSString *str = @"veryLongHTMLSTRING";
NSLog(@"Original test: %@",[str substringToIndex:500]);
NSError *error = nil;
// use regular expression to replace the emoji
NSRegularExpression *regex = [NSRegularExpression
                                  regularExpressionWithPattern:@"\\[pic:([^\\s:\\]]+):([^\\]])\\]"
                                  options:NSRegularExpressionCaseInsensitive error:&error];
if(error != nil){
    NSLog(@"ERror: %@",error);
}else{
    [regex stringByReplacingMatchesInString:str
                                    options:0
                                      range:NSMakeRange(0, [str length])
                               withTemplate:[NSString stringWithFormat:@"/%@/photo/%@.gif",
                                             IMAGE_BASE_URL, @"$1/$2"]];

NSLog(@"Replaced test: %@",[str substringToIndex:500]);
2
  • What do you expect the final result to be? Commented Jan 13, 2013 at 16:16
  • I expect the [pic:brand:123] to be /photo/brand/123.gif. brand is generic here though. It could between anything between numerous options. Commented Jan 13, 2013 at 16:19

2 Answers 2

8

I see two errors: There is a + missing in the second capture group of the regex pattern, it should be

NSString *pattern = @"\\[pic:([^\\s:\\]]+):([^\\]]+)\\]";

And stringByReplacingMatchesInString returns a new string, it does not replace the matched string. So you must assign the result to a new string, or use replaceMatchesInString:options:range:withTemplate: with a NSMutableString.

The following modifed code

NSString *pattern = @"\\[pic:([^\\s:\\]]+):([^\\]]+)\\]";
NSString *str = @"bla bla [pic:brand:123] bla bla";
NSLog(@"Original test: %@",str);
NSError *error = nil;
NSRegularExpression *regex = [NSRegularExpression
                              regularExpressionWithPattern:pattern
                              options:NSRegularExpressionCaseInsensitive error:&error];
if(error != nil){
    NSLog(@"ERror: %@",error);
} else{
    NSString *replaced = [regex stringByReplacingMatchesInString:str
                                    options:0
                                      range:NSMakeRange(0, [str length])
                               withTemplate:[NSString stringWithFormat:@"/%@/photo/%@.gif",
                                             @"IMAGE_BASE_URL", @"$1/$2"]];

    NSLog(@"Replaced test: %@",replaced);
}

produces the output

Original test: bla bla [pic:brand:123] bla bla
Replaced test: bla bla /IMAGE_BASE_URL/photo/brand/123.gif bla bla
Sign up to request clarification or add additional context in comments.

2 Comments

You are absolutely right, damn I need to stop overworking my eyes! Thanks alot!
@shawndreck See my solution as well. :)
2

You're misunderstanding how the template should be formed. Also, stringByReplacingMatchesInString doesn't alter the original string. Try this (tested):

NSString *target = @"longHTML [pic:whatever:123] longHTMLcontinues";
NSMutableString *s = [target mutableCopy];

NSError *err = nil;
NSRegularExpression *expr = [NSRegularExpression regularExpressionWithPattern:@"\\[pic\\:([a-zA-Z0-9]*)\\:([a-zA-Z0-9]*)\\]" options:0 error:&err];
if (err) {
    NSLog(@"%@", err);
    exit(-1);
}

[expr replaceMatchesInString:s options:0 range:NSMakeRange(0, s.length) withTemplate:@"/photo/$1/$2.gif"];

4 Comments

Thanks for heads up. But what I'm confusing with the template? I shouldn't be using [NSString stringWithFormat:....?
@shawndreck No. That's unnecessary. The template is a format itself. /photo/$1/$2.gif tells the regex object to substitute the first group in place of $1, etc.
The reason I used stringWithFormat was to be able to include the nsstring constant IMAGE_BASE_URL defined somewhere earlier in my code. I could not simply do /IMAGE_BASE_URL/photo/... because that will only put the literal IMAGE_BASE_URL in my link. Which is definetely not what I am after. But I understand what you have said.
@shawndreck I see what you are saying about IMAGE_BASE_URL. However, there is no need to substitute in "$1/$2" via string formating. It doesn't change. Take it out of the variable args. Move it to the format string. [NSString stringWithFormat:@"/%@/photo/$1/$2.gif", @"IMAGE_BASE_URL"] Keep It Simple.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.