NSString是什么样的:实际上是什么?

时间:2016-03-09 21:27:13

标签: objective-c cocoa nsstring

我正在试图找出isLike:NSString实际做了什么并遇到麻烦。 Apple的own documentation非常模糊:

  

返回一个布尔值,指示接收器是否“喜欢”   另一个给定的对象。

     

...

     

NSObject方法提供此方法的默认实现   返回NONSString还提供了此方法的实现,   如果接收器匹配描述的模式,则返回YES   对象

它提到了一个“模式”,但是通过一些基本的测试,它似乎没有使用正则表达式。在这种情况下,模式格式究竟是什么?

2 个答案:

答案 0 :(得分:11)

正如其他人发布的那样,Apple的文档没有详细描述[NSString isLike:]的行为,如here所示:

  

NSObject方法提供的此方法的默认实现返回NO。 NSString还提供了此方法的实现,如果接收器匹配object描述的模式,则返回YES。

正如其他人所说,它可能基于NSPredicate。如果是,则NSComparisonPredicate可能会使用here所述的运算符类型NSLikePredicateOperatorType

  

NSMatchesPredicateOperatorType

     

完整的正则表达式匹配谓词。

     

在OS X v10.4及更高版本中可用。

     

NSLikePredicateOperatorType

     

MATCHES谓词的一个简单子集,与SQL LIKE的行为类似。

     

在OS X v10.4及更高版本中可用。

虽然功能可能是正则表达式的简单子集,但语法肯定是不同的。我在OS X 10.10.5今天本地测试了以下内容:

- (NSString *)escapeString:(NSString *)value {
    return [value stringByReplacingOccurrencesOfString:@"\\" withString:@"\\\\"];
}

- (void)is:(NSString *)value like:(NSString *)pattern note:(NSString *)note {
    NSLog(@"[@\"%@\" isLike:@\"%@\"] == %@ // %@",
            [self escapeString:value],
            [self escapeString:pattern],
            ([value isLike:pattern] ? @"true" : @"false"),
            note);
}

- (void)testAll {
    // each note contains result on OS X 10.10.5 on 20160503
    [self is:@"foo" like:@"f*" note:@"true, '*' wildcard works like file globbing, not RE"];
    [self is:@"foo" like:@"foo*" note:@"true, '*' is zero or more"];
    [self is:@"foo" like:@"f?o" note:@"true, '?' wildcard works like file globbing, not RE"];
    [self is:@"foo" like:@"f?" note:@"false, not more then one"];
    [self is:@"foo" like:@"f?oo" note:@"false, not less than one"];
    [self is:@"foo" like:@"Foo" note:@"false, is case-sensitive (also see isCaseInsensitiveLike:)"];
    [self is:@"foo" like:@"[Ff]oo" note:@"true, supports character classes"];
    [self is:@"foo" like:@"[^F]oo" note:@"false, does not support RE negation in character classes"];
    [self is:@"foo" like:@"[a-z]oo" note:@"true, supports ranges"];
    [self is:@"foo" like:@"[[:lower:]]oo" note:@"false, does not support POSIX named classes"];
    [self is:@"]oo" like:@"[]]oo" note:@"false, does not support ']' as first character in a class"];
    [self is:@"]oo" like:@"[\\]]oo" note:@"true, backslash to escape interpretation of ']' as end of class"];
    [self is:@"[oo" like:@"\\[oo" note:@"true, backslash to escape interpretation as start of class"];
    [self is:@"-oo" like:@"[x\\-z]oo" note:@"true, supports escape of '-' in character classes"];
    [self is:@"?oo" like:@"\\?oo" note:@"true, escape with backslash"];
    [self is:@"foo" like:@"\\?oo" note:@"false, this is not just wildcard matching"];
    [self is:@"*oo" like:@"\\*oo" note:@"true, escape with backslash"];
    [self is:@"foo" like:@"\\*oo" note:@"false, this is not just wildcard matching"];
    [self is:@"\\foo" like:@"\\\\*oo" note:@"true, escape backslash with another backslash"];
}

此代码产生以下结果:

[@"foo" isLike:@"f*"] == true // true, '*' wildcard works like file globbing, not RE
[@"foo" isLike:@"foo*"] == true // true, '*' is zero or more
[@"foo" isLike:@"f?o"] == true // true, '?' wildcard works like file globbing, not RE
[@"foo" isLike:@"f?"] == false // false, not more then one
[@"foo" isLike:@"f?oo"] == false // false, not less than one
[@"foo" isLike:@"Foo"] == false // false, is case-sensitive (also see isCaseInsensitiveLike:)
[@"foo" isLike:@"[Ff]oo"] == true // true, supports character classes
[@"foo" isLike:@"[^F]oo"] == false // false, does not support RE negation in character classes
[@"foo" isLike:@"[a-z]oo"] == true // true, supports ranges
[@"foo" isLike:@"[[:lower:]]oo"] == false // false, does not support POSIX named classes
[@"]oo" isLike:@"[]]oo"] == false // false, does not support ']' as first character in a class
[@"]oo" isLike:@"[\\]]oo"] == true // true, backslash to escape interpretation of ']' as end of class
[@"[oo" isLike:@"\\[oo"] == true // true, backslash to escape interpretation as start of class
[@"-oo" isLike:@"[x\\-z]oo"] == true // true, supports escape of '-' in character classes
[@"?oo" isLike:@"\\?oo"] == true // true, escape with backslash
[@"foo" isLike:@"\\?oo"] == false // false, this is not just wildcard matching
[@"*oo" isLike:@"\\*oo"] == true // true, escape with backslash
[@"foo" isLike:@"\\*oo"] == false // false, this is not just wildcard matching
[@"\\foo" isLike:@"\\\\*oo"] == true // true, escape backslash with another backslash

因此,isLike:似乎支持?*,例如使用反斜杠\进行文件通配以逃避特殊解释。它还支持[]的字符类,其范围定义为-。反斜杠以逃避打开[,反斜杠以转义类中的]-

答案 1 :(得分:8)

标题NSScriptWhoseTest.h提供了更多信息:

@interface NSObject (NSComparisonMethods)
...

- (BOOL)isLike:(NSString *)object;
    // argument should be a string using simple shell wildcards (* and ?).
    // (e.g. "Stev*" or "N?XT").
    // Returns NO if receiver is not an NSString.

- (BOOL)isCaseInsensitiveLike:(NSString *)object;

@end