Objective-C可可应用程序中的正则表达式


173

初始谷歌搜索表明在Objective-C Cocoa应用程序中没有内置的方式来执行正则表达式。

所以有四个问题:

  1. 是真的吗

  2. 你在跟我开玩笑吗?

  3. 好的,那么您推荐一个不错的开源库吗?

  4. 有什么方法可以导入NSScanner类而无需导入库就足够接近?


4
嗯...我想知道如果您使用Monotouch会发生什么。+1问题。
丹·罗森斯塔克

Answers:



42
  1. 是的,可可中没有正则表达式支持。如果您只对布尔匹配感兴趣,可以使用NSPredicate支持ICU正则表达式语法的。但是通常您对匹配的位置或子表达式的位置感兴趣,而NSPredicate无法获得它。
  2. 如前所述,您可以使用regex POSIX函数。但是它们被认为很慢,与其他解决方案(ICU / pcre)相比,正则表达式的语法受到限制。
  3. 有许多OSS库,CocoaDev拥有广泛的清单
  4. 例如,RegExKitLite不需要任何库,只需将.m和.h添加到您的项目中。

    (我对RegExKitLite的抱怨是它通过类别扩展了NSString,但它也可以被认为是一项功能。它还使用了操作系统随附的非公开ICU库,Apple不建议这样做。)


3
请记住,POSIX正则表达式功能不适用于unicode(仅ASCII)。
汤姆·达林

仅供参考,NSPredicate url是一个损坏的链接
Taber

11
iOS支持子字符串搜索的正则表达式,例如[myString rangeOfString:@"regex_here" options:NSRegularExpressionSearch]
Nestor

1
在Lion(10.7)中也可用#if MAC_OS_X_VERSION_10_7 <= MAC_OS_X_VERSION_MAX_ALLOWED || __IPHONE_3_2 <= __IPHONE_OS_VERSION_MAX_ALLOWED
Maciej Swic 2011年

我发现使用非公开ICU库很好,因为如果您需要使用它,那是因为您的Cocoa版本中没有内置的正则表达式支持。如果使用这些库,则也意味着您正在为较旧的系统进行构建,由于不再受支持,因此将不再更改。如果要同时针对新旧版本进行构建,则如果NSRegularExpression不存在,则可以使用RegExKitLite作为后备。(是的,仍然有人在使用旧系统。)

19

RegexKit是我发现的最好的。非常可可:是。我在我们的多个iPhone应用程序中使用的是“ Lite”版本:

源伪造

Lingonikorg


1
我第二个RegexKit Lite。非常好!
Dave Dribin 09年

1
太酷了,使用它的人越多,它可能会变得更好!
avocade

12

您可以使用POSIX正则表达式库(对于POSIX兼容OS为是)。尝试

man 3 regex

哦,我明白了。这是在直接C语言中执行此操作的一种方法,该方法应该可以在任何Objective-C应用程序中使用。太好了,谢谢!这基本上是公认的方法吗?
dreeves

这是一种方式,不需要任何其他依赖项。就可以导入的开源库而言,还有其他选择(对于Perl正则表达式,PCRE,如果使用的是Obj-C ++,则为Boost RegEx库,或者其他答案中列出的其他)。
亚当·赖特

将直线C与Objective-C混合使用有什么缺点?您能否包括一个用于与NSString相互转换的代码段?再次感谢!
dreeves

Objective-C建立在C之上,因此您并没有真正混合任何东西。不过,大多数人都使用库,因为它提供了更易于使用的API。
Marc Charbonneau

5
并且因为POSIX regex函数仅适用于ASCII字符串。
汤姆·达林

8

我用来解决REGEX和JSON解析问题的廉价又肮脏的hack解决方案是创建一个UIWebView对象并注入Javascript函数来进行解析。然后,javascript函数将返回一个我关心的值(或值列表)的字符串。实际上,您可以存储一小组针对特定任务定制的函数库,然后根据需要调用它们。

我不知道这种技术是否可以扩展到大量重复的解析请求,但是对于快速事务处理的东西,它可以完成工作而无需依赖任何您可能不理解的外部资源或代码。


7

我喜欢使用PCRE的AGRegex框架,如果您习惯使用PCRE语法,则非常方便。该框架的最佳版本是Colloquy IRC客户端中的版本,因为它已升级为使用PCRE 6.7:

http://colloquy.info/project/browser/trunk/Frameworks/AGRegex

它非常轻巧,比RegExKit强得多(尽管当然不那么强大)。


如果它具有完全与Perl兼容的正则表达式,为什么功能不那么强大?
dreeves,2009年

关联的Objective-C帮助程序方法不如RegExKit中的方法那么广泛,但是对于大多数用途而言,它们是很好的。
罗布·肯尼格


5

在搜索该主题期间,我遇到了CocoaOniguruma,它使用Oniguruma(Ruby1.9和PHP5之后的正则表达式引擎)。与现有的OregKit(日语)相比,似乎有点新。不确定这些如何与其他绑定堆叠在一起。


4

谷歌搜索小工具,找到此库: RegexOnN​​SString

开源库,包含如下功能:

-(NSString *) stringByReplacingRegexPattern:(NSString *)regex withString:(NSString *) replacement caseInsensitive:(BOOL)ignoreCase

和使用NSRegularExpression类。非常易于使用,无需担心任何事情。

请注意 NSRegularExpression,如Datasmid所述功能自Mac OS X v10.7和IOS 4.0起可用。


1

我很容易 我将一个新的C ++文件添加到我的Objective C项目中,将其重命名为.mm,然后在其中创建一个标准C ++类。然后,在“ public:”部分中为C ++函数创建一个静态类方法,该函数采用NSString并返回NSString(或NSArray(如果需要的话))。然后,我将NSString转换为C ++ std :: string,如下所示:

// If anyone knows a more efficient way, let me know in the comments.
// The "if" condition below is because ObjC crashes if converting to
// std::string if the string is nil or empty.
// assume #include <string>
std::string s = "";
if (([sInput != nil]) && (!([sInput isEqualTo:@""]))) {
  std::string sTemp([sInput UTF8String]);
  s = sTemp;
}

从那里,我可以像这样使用regex_replace:

// assume #include <regex>
std::string sResult = std::regex_replace(sSource,sRegExp,sReplaceWith);

然后,我可以使用以下命令将std :: string转换回NSString:

NSString *sResponse2 = @(sResult.c_str());

如果仅将此C ++用于此函数,则可能会适合调用此文件extra.mm(类名Extra)并放入此静态类方法,然后在情况出现时添加其他静态类方法在C ++中这样做才有意义,因为在某些情况下,它的麻烦程度较小。(在某些情况下,ObjC用更少的代码行执行某些操作,而在某些情况下,C ++用更少的代码行执行此操作。)

PS还有另一种方法是使用.mm文件,但使用std :: string和std :: regex_replace()(或regex_match())进行Objective C包装。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.