0

I have a huge amount of NSStrings in a database that get passed to a view controller in an iOS app. They are formatted as "This is a message with $specially formatted$ content".

However, I need to change the '$' at the start of the special formatting with a '[' and the '$' at the end with ']'. I have a feeling I can use an NSScanner but so far all of my attempts have produced wackily concatenated strings!

Is there a simple way to recognise a substring encapsulated by '$' and swap them out with start/end characters? Please note that a lot of the NSStrings have multiple '$' substrings.

Thanks!

Sarreph
  • 1,986
  • 2
  • 19
  • 41
  • Is this an internal database or a database your app is connecting to? – propstm Dec 07 '12 at 13:09
  • It's a Core Data model that throws objects into an array for me. However, the persistent store is full of NSStrings so I provided context to illustrate the fact I don't want to do a find and replace before runtime. – Sarreph Dec 07 '12 at 14:26

5 Answers5

2

You can use regular expressions:

NSMutableString *str = [@"Hello $World$, foo $bar$." mutableCopy];

NSRegularExpression *regex;
regex = [NSRegularExpression regularExpressionWithPattern:@"\\$([^$]*)\\$"
                                                  options:0
                                                    error:NULL];
[regex replaceMatchesInString:str
                      options:0
                        range:NSMakeRange(0, [str length])
                 withTemplate:@"[$1]"];
NSLog(@"%@", str);
// Output:
// Hello [World], foo [bar].

The pattern @"\\$([^$]*)\\$" searches for

$<zero_or_more_characters_which_are_not_a_dollarsign>$

and all occurrences are then replaced by [...]. The pattern contains so many backslashes because the $ must be escaped in the regular expression pattern.

There is also stringByReplacingMatchesInString if you want to create a new string instead of modifying the original string.

Martin R
  • 529,903
  • 94
  • 1,240
  • 1,382
  • Thanks, it works really well! However, I am unfamiliar with NSRegularExpression pattern formatting and need to change '[' to a '\\['; how should I modify the template to accommodate the escaped backslash? – Sarreph Dec 07 '12 at 14:20
  • Yes please :) - I've tried including a double-backslash in the template before each `[` but that doesn't seem to work... – Sarreph Dec 07 '12 at 14:25
  • @Rorz: You need 4 backslashes (-: – Martin R Dec 07 '12 at 14:26
  • So it kind of double-escapes the `[`? Interesting! Works perfectly: amazing! – Sarreph Dec 07 '12 at 14:27
  • @Rorz: The "\" must be escaped as "\\" in a regex pattern because is has a special meaning as escape character. But to get 2 backslashes in a string you have to write "\\\\" .... – Martin R Dec 07 '12 at 14:32
1

I think replaceOccurrencesOfString: won't work cause you have start$ and end$.

But if you seperate the Strings with [string componentsSeperatedByString:@"$"] you get an Array of substrings, so every second string is your "$specially formatted$"-string

xapslock
  • 1,119
  • 8
  • 21
1

This should work!

NSString *str = @"This is a message with $specially formatted$ content";
NSString *original = @"$";
NSString *replacement1 = @"[";
NSString *replacement2 = @"]";

BOOL start = YES;
NSRange rOriginal = [str rangeOfString: original];
while (NSNotFound != rOriginal.location) {
    str = [str stringByReplacingCharactersInRange: rOriginal withString:(start?replacement1:replacement2)];
    start = !start;
    rOriginal = [str rangeOfString: original];
}

NSLog(@"%@", str);

Enjoy Programming!

Asif Mujteba
  • 4,596
  • 2
  • 22
  • 38
  • Thanks, cyberpawn, but when I tried to compile it it threw a malloc error back in my face :( – Sarreph Dec 07 '12 at 13:39
  • i added this line "rOriginal = [str rangeOfString: original];" in while loop after a few minutes did you used the modified code? and are you getting this error on compile time or runtime? – Asif Mujteba Dec 07 '12 at 13:43
  • Ah it works now :) but I decided to go with the NSRegularExpression for my implementation as it's more relevant and efficient for what I need to do. I shall be saving this as a code snippet, though! – Sarreph Dec 07 '12 at 14:14
1
// string = @"This is a $special markup$ sentence."
NSArray *components = [string componentsSeparatedByString:@"$"];
// sanity checks
if (components.count < 2) return; // maybe no $ characters found
if (components.count % 2) return; // not an even number of $s
NSMutableString *out = [NSMutableString string];
for (int i=0; i< components.count; i++) {
   [out appendString:components[i]];
   [out appendString: (i % 2) ? @"]" : @"[" ];
}
// out = @"This is a [special markup] sentence."
Mundi
  • 79,884
  • 17
  • 117
  • 140
  • Thanks for the response, one slight problem is that it seems to append an extra '[' on the end of `out` – Sarreph Dec 07 '12 at 13:40
0

Try this one

NSMutableString *string=[[NSMutableString alloc]initWithString:@"This is a message with $specially formatted$ content. This is a message with $specially formatted$ content"];


NSMutableString *string=[[NSMutableString alloc]initWithString:@"This is a message with $specially formatted$ content. This is a message with $specially formatted$ content"];

BOOL open=YES;
for (NSUInteger i=0; i<[string length];i++) {
    if ([string characterAtIndex:i]=='$') {
        if (open) {
            [string replaceCharactersInRange:NSMakeRange(i, 1) withString:@"["];
            open=!open;
        }
        else{
            [string replaceCharactersInRange:NSMakeRange(i, 1) withString:@"]"];
            open=!open;
        }
    }
}
NSLog(@"-->%@",string);

Output:

-->This is a message with [specially formatted] content. This is a message with [specially formatted] content
Anoop Vaidya
  • 46,283
  • 15
  • 111
  • 140