Find every strings between 2 specific strings...

Hello all,

I’m a bit stumped right now. Say I have this string:

I wish to find every strings in this example (i.e. test and find), but so far the objective-c method I found only finds the first one (i.e. test). This is not enough. Standard NSString methods were not enough.

Here is the objective-c method I am using:

- (NSString*) findStringBetweenString:(NSString*)start andString:(NSString*)end insideString:(NSString*)theStringToSearch {
    NSScanner* scanner = [NSScanner scannerWithString:theStringToSearch];
    [scanner setCharactersToBeSkipped:nil];
    [scanner scanUpToString:start intoString:NULL];
    if ([scanner scanString:start intoString:NULL]) {
        NSString* result = nil;
        if ([scanner scanUpToString:end intoString:&result]) { return result; }
    }
    return nil;
}

Thus I need an NSMutableArray with NSString objects returned by this method.

Does anyone have any pointer? Tx!

Model: MacBookPro8,2
Browser: Safari 534.51.22
Operating System: Mac OS X (10.7)

Hi,

try this


- (NSArray*)findStringsBetweenString:(NSString *)start 
                            andString:(NSString *)end 
                         insideString:(NSString *)theStringToSearch 
{
    if (start == nil || end == nil || theStringToSearch == nil) return nil;
        
    NSMutableArray *resultArray = [NSMutableArray array];
    NSScanner* scanner = [NSScanner scannerWithString:theStringToSearch];
    NSString *foundString;
    
	while ([scanner isAtEnd] == NO) {
		if ([scanner scanUpToString:start intoString:NULL] && [scanner scanString:start intoString:NULL] && [scanner scanUpToString:end intoString:&foundString]) {
			[resultArray addObject:foundString];
            [scanner scanString:end intoString:NULL];
        }
	}
    return resultArray;
}


This is beautiful! Tx! I suspected that NSScanner was the way to go, but my ignorance about this class was stopping my progress…

One thing though. Right now, it loops indefinitely in the “while” loop, the if’s conditions never seem to get a positive answer… I cannot find what’s wrong with it, due again to my limited knowledge of this class.

Perhaps the if’s conditions are too restrictive?

Model: MacBookPro8,2
Browser: Safari 534.51.22
Operating System: Mac OS X (10.7)

It worked for me. How did you call it?

Ric

Like this:

NSArray* result = [self findStringsBetweenString:@"##" andString:@"##" insideString:[currentItemLevel1 valueForKey:@"levelOneFolderName"]];

the “[currentItemLevel1 valueForKey:@“levelOneFolderName”]” returns an NSString, that is confirmed.

the method calling and the method being called are both in the same implementation file.

Tried various things, nothing worked so far.

And does [currentItemLevel1 valueForKey:@“levelOneFolderName”] return a string that has “##” in it? One condition I found that cause an endless loop is if you have “####” in your string.

Ric

I think you may be on to something… When it begins with ##, like this:

it loops indefinitely. Does not when it is at the end, like this:

didn’t try “####”, but i’m sure it does the same problem… This could be problematic. If only I could use NSRegularExpression in 10.6… I know regex very well. :frowning:

Model: MacBookPro8,2
Browser: Safari 534.51.22
Operating System: Mac OS X (10.7)

Another way to do it would be to use componentsSeparatedByString:

This method logs the strings between the double number signs (if the separator is present as the first thing in the string, the array created has an empty string as the first member, so you still want every odd member of the array).

on applicationWillFinishLaunching_(aNotification)
        set ts to current application's NSString's stringWithString_("##a test## string with a ##couple of## things inside some ##numbersigns## with other junk")
        set sep to current application's NSString's stringWithString_("##")
        if ts's rangeOfString_(sep)'s |length| as integer is not 0 then 
            set componentsArray to ts's componentsSeparatedByString_("##")
            repeat with i from 1 to componentsArray's |count|() by 2
                log componentsArray's objectAtIndex_(i)
                if i+2 > (componentsArray's |count|() as integer -1) then exit repeat
            end repeat
        else
            log "the separator is not present"
        end if
	end applicationWillFinishLaunching_

Ric

You could always use RegExKitLite. It’s pretty simple to add to a project, and it’s very easy to use because its methods are added as categories to NSString and NSMutableString. componentsMatchedByRegex: will then probably make you a happy person…

regexkit.sourceforge.net/RegexKitLite/

This is great!!! Wow, why is it so hard to learn about these things? That’s perfect and it also solves another problem I had somewhere else.

Thanks Shane, will definitely try this!

One small question: this project is under BSD license, is this allowed for the Mac app store and iOS app store? I seem to remember that yes it is, just seeking confirmation…

Browser: Safari 6533.18.5
Operating System: Mac OS X (10.6)

I don’t think the licence is a problem, but there was some discussion of apps being rejected for other reasons. I never followed it up because I’m not using it in anything for the stores.

Alright. I think it’ll be fine, everything else I use is in the standard appkit…

Thanks again everyone!

Browser: Safari 6533.18.5
Operating System: Mac OS X (10.6)

Yes, this version of the loop should consider if the delimiter strings are at the beginning or end


while ([scanner isAtEnd] == NO) {
       [scanner scanUpToString:start intoString:NULL];
		if ([scanner scanString:start intoString:NULL] && [scanner scanUpToString:end intoString:&foundString] && [scanner scanString:end intoString:NULL]) {
			[resultArray addObject:foundString];
        }
	}

Yep, that worked too Stefan. Tx!

I’ll still have a look at the RegexKitLite thing, for me it is much easier to master as I know regex really well.

Tx everyone! :slight_smile: