Objective-C 字符串分割问题

3
我正在尝试将一个字符串拆分成NSArray,但是我遇到了一个问题,无法忽略带有引号的字符串。
例如:
NSString *example = @"100 200 300 \"TEST ITEM\" 500";
NSArray *array = [example componentsSeparatedByString:@" "];

然而数组显然被创建为100、100、300、"Test,ITEM"、500。是否可能将带有" "的任何内容视为一个整体?谢谢。

首先按照 " 进行分割,然后在偶数元素(0、2、...)上进行空格分割。 - Kevin
@Kevin 那么带有三个单词的引号内句子怎么处理? - rmaddy
@rmaddy,这就是我说的偶数元素。@"a b \"c d e\" f g" -> @[@"a b ", @"c d e", @" f g"],分割偶数 -> @[@"a", @"b", @"c d e", @"f", @"g"](注意删除空元素)。 - Kevin
2个回答

5
你可以使用一个众所周知的CSV解析器(CHCSVParser),它可以配置为使用空格作为分隔符,并且会正确处理双引号。这假设你想要像通常处理CSV一样转义双引号等。
否则,你可能需要自己编写解析逻辑。可以看看NSScanner,它可以让你读取到一个空格或双引号,查看你得到了什么,然后再读取到下一个空格/双引号等。
例如:
@interface ItemParser : NSObject<CHCSVParserDelegate>

- (NSArray *)itemsFromString:(NSString *)input;

@end

@implementation ItemParser {
    NSMutableArray *_results;
}

- (NSArray *)itemsFromString:(NSString *)input {
    _results = [NSMutableArray array];

    NSStringEncoding encoding = [input fastestEncoding];
        NSInputStream *stream = [NSInputStream inputStreamWithData:[input dataUsingEncoding:encoding]];
    CHCSVParser *parser = [[CHCSVParser alloc] initWithInputStream:stream usedEncoding:&encoding delimiter:' '];
    parser.delegate = self;
    [parser parse];

    return _results;
}

- (void)parser:(CHCSVParser *)parser didReadField:(NSString *)field atIndex:(NSInteger)fieldIndex {
    [_results addObject:field];
}
@end

您可以像这样使用它:

NSString *example = @"100 200 300 \"TEST ITEM\" 500";
ItemParser *parser = [[ItemParser alloc] init];
NSLog(@"%@", [parser itemsFromString:example]);

谢谢你回复我。我已经研究了CHCSVParser,从介绍上看它似乎可以满足我的需求。但是我将其添加到我的项目中,却无法解析。例如:NSString *example = @"100 200 300 "TEST ITEM" 500"; NSArray *test = [NSArray arrayWithContentsOfCSVFile:example options:(CHCSVParserOptionsRecognizesComments)]; 我只得到空元素? - Strikeforce
@Strikeforce,你调用的方法需要一个文件路径;我不知道为什么它没有提供比你看到的更好的错误信息。如果你想配置CHCSVParser使用空格作为分隔符,你需要直接创建解析器的实例。我会在我的答案中更新一个示例。 - Jesse Rusak

1
这是一个使用 NSScanner 将字符串按照不同种类的引号("", '', ‘’, “”)分割成搜索词的 NSString 分类方法。

用法:

NSArray *terms = [@"This is my \"search phrase\" I want to split" searchTerms];
// results in: ["This", "is", "my", "search phrase", "I", "want", "to", "split"]

代码:

@interface NSString (Search)
- (NSArray *)searchTerms;
@end

@implementation NSString (Search)

- (NSArray *)searchTerms {

    // Strip whitespace and setup scanner
    NSCharacterSet *whitespace = [NSCharacterSet whitespaceAndNewlineCharacterSet];
    NSString *searchString = [self stringByTrimmingCharactersInSet:whitespace];
    NSScanner *scanner = [NSScanner scannerWithString:searchString];
    [scanner setCharactersToBeSkipped:nil]; // we'll handle whitespace ourselves

    // A few types of quote pairs to check
    NSDictionary *quotePairs = @{@"\"": @"\"",
                                 @"'": @"'",
                                 @"\u2018": @"\u2019",
                                 @"\u201C": @"\u201D"};

    // Scan
    NSMutableArray *results = [[NSMutableArray alloc] init];
    NSString *substring = nil;
    while (scanner.scanLocation < searchString.length) {
        // Check for quote at beginning of string
        unichar unicharacter = [self characterAtIndex:scanner.scanLocation];
        NSString *startQuote = [NSString stringWithFormat:@"%C", unicharacter];
        NSString *endQuote = [quotePairs objectForKey:startQuote];
        if (endQuote != nil) { // if it's a valid start quote we'll have an end quote
            // Scan quoted phrase into substring (skipping start & end quotes)
            [scanner scanString:startQuote intoString:nil];
            [scanner scanUpToString:endQuote intoString:&substring];
            [scanner scanString:endQuote intoString:nil];
        } else {
            // Single word that is non-quoted
            [scanner scanUpToCharactersFromSet:whitespace intoString:&substring];
        }
        // Process and add the substring to results
        if (substring) {
            substring = [substring stringByTrimmingCharactersInSet:whitespace];
            if (substring.length) [results addObject:substring];
        }
        // Skip to next word
        [scanner scanCharactersFromSet:whitespace intoString:nil];
    }

    // Return non-mutable array
    return results.copy;

}

@end

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接