在 NSPredicate 中使用带有 ISBN 数字示例的正则表达式令人困惑

Posted

技术标签:

【中文标题】在 NSPredicate 中使用带有 ISBN 数字示例的正则表达式令人困惑【英文标题】:Confusing on regular expression using in NSPredicate with ISBN numbers example 【发布时间】:2014-01-09 09:14:50 【问题描述】:

Apple 文档在描述如何在 NSPredicate 中使用正则表达式时给出了一个示例。

NSArray *isbnTestArray = @[@"123456789X", @"987654321x", @"1234567890", @"12345X", @"1234567890X"];
NSPredicate *isbnPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES '\\\\d10|\\\\d9[Xx]'"];
NSArray *isbnArray = [isbnTestArray filteredArrayUsingPredicate:isbnPredicate];

我的问题是为什么它使用\\\\d 而不是\\d\d

【问题讨论】:

【参考方案1】: 数字的正则表达式模式是\d。 在谓词'…' 的文字字符串中,每个反斜杠都必须被转义,所以你得到\\d。 谓词在文字NSString 中定义,因此反斜杠必须再次转义,得到\\\\d

如果在谓词中使用%@ 格式而不是文字字符串,则可以避免一个转义步骤:

NSString *pattern = @"\\d10|\\d9[Xx]";
NSPredicate *isbnPredicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", pattern];

对谓词中的所有变量部分使用%@ 通常会更好,因为它可以避免 各种引用和转义问题。

【讨论】:

另一个问题,为什么我们可以写成NSString *pattern = @"\\d10|\\d9[Xx]";而不是NSString *pattern = @"\\\\d10|\\\\d9[Xx]"; @KudoCC: NSString *pattern = @"\\\\d10|\\\\d9[Xx]" 存储为字符串"\\d10|\\d9[Xx]",这将匹配文字反斜杠字符后跟 10 个“d”字符。 但是为什么它不会在[NSPredicate predicateWithFormat:@"SELF MATCHES %@", pattern];中再次被转义? @KudoCC:谓词在内部表示为 NSComparisonPredicate ,而不是字符串,因此不会有额外的转义。您不必担心。【参考方案2】:

大多数编程语言使用\ 作为转义序列。

当你这样写时:

 SELF MATCHES '\\\\d10|\\\\d9[Xx]'

每个\都会转义下一个字符,它会变成:

SELF MATCHES '\\d10|\\d9[Xx]'

为什么不使用 \d ?

如果你像这样使用:

SELF MATCHES '\d10|\d9[Xx]'

在正则表达式中会改为:

SELF MATCHES 'd10|d9[Xx]'

为什么不使用 \d ?

如果你像这样使用:

SELF MATCHES '\\d10|\\d9[Xx]'

在正则表达式中会改为:

SELF MATCHES '\d10|\d9[Xx]'

但在正则表达式中,\d 将被视为转义序列,并将其视为d10|d9[Xx]

【讨论】:

"如果你使用:SELF MATCHES '\d10|\d9[Xx]' 它会变成这样:SELF MATCHES 'd10|d9 [Xx]'",是真的吗? @KudoCC: 表示它将被视为转义序列。

以上是关于在 NSPredicate 中使用带有 ISBN 数字示例的正则表达式令人困惑的主要内容,如果未能解决你的问题,请参考以下文章

使用 NSPredicate 解析带有变量的公式

带有核心数据的 NSPredicate,在字符串属性中搜索带有边界的单词

如何在 iOS 的核心数据中创建和使用带有查询的 NSPredicate?

带有 NSPredicate 的 Fetchrequest 不返回正确的值

带有核心数据对象的 NSPredicate

带有特殊字符的 NSPredicate 过滤