我真的很想把RegexKit (或者我自己的libpcre包装器)放到我的项目中去,但是在我这么做之前,我想知道Cocoa开发人员是如何在没有真正复杂的代码或者没有与RegexKit或其他正则表达式库链接的情况下完成这些基本内容的。
我发现Cocoa不包含任何正则表达式匹配特性,这让人目瞪口呆。我已经习惯于将正则表达式用于所有类型的事情,没有正则表达式我就会迷失方向。没有它们,我可以做我需要的事情,但是代码会相当复杂。所以,可可神,我问你,“可可之路”是怎么做的.
就我而言,这个问题是编程中的一个日常问题。可可必须有办法用内置的功能来做到这一点。注意,我想匹配的元素的位置会发生变化,有时还会出现“引号”。空白是可变的。
以下列字符串为例:
Content-Type: application/xml; charset=utf-8
Content-Type: text/html; charset="iso-8859-1"
Content-Type: text/plain;
charset=us-ascii
Content-Type: text/plain; name="example.txt"; charset=utf-8从所有这些字符串中,您将如何使用内置的Cocoa类来确定mime类型(例如文本/平原)和字符集(例如utf-8)?
我最终会执行一系列的-rangeOfString:和子字符串调用,使用条件检查来处理可选的引号等等。有什么方法可以用NSScanner来完成吗?在我看来,NSScanner类似乎有一个相当天真的API。
类似于C的sscanf(),它适用于NSString对象,这将是一个理想的选择。我的大多数字符串解析需求都很简单,比如本例,所以,虽然我习惯了正则表达式,但它们是不是太过了呢?
编辑:代码有点长,但是事实证明NSScanner实际上很容易使用。它基本上是沿着你的绳子走,照你说的做。创建它需要的NSCharacterSet实例中最烦人的部分。
- (void)testNSScannerUseCase {
NSString *testString = @"Content-type: application/xml; name=\"test\";\n charset=\"utf-8\"";
unsigned int a = 'a', zero = '0';
// There's probably a quicker way than to make these character sets this way
NSMutableCharacterSet *alphaNumSet = [NSMutableCharacterSet characterSetWithRange:NSMakeRange(a, 26)];
[alphaNumSet addCharactersInRange:NSMakeRange(zero, 10)];
NSMutableCharacterSet *mimeTypeSet = [NSMutableCharacterSet characterSetWithCharactersInString:@"/-"];
[mimeTypeSet formUnionWithCharacterSet:alphaNumSet];
NSMutableCharacterSet *charsetSet = [NSMutableCharacterSet characterSetWithCharactersInString:@"-"];
[charsetSet formUnionWithCharacterSet:alphaNumSet];
// Initialize a case-insensitive scanner
NSScanner *scanner = [NSScanner scannerWithString:testString];
[scanner setCaseSensitive:NO];
// Prepare to capture mime-type
NSString *mimeType = nil;
// Skip past the Content-Type: section
if ([scanner scanUpToString:@":" intoString:NULL] && [scanner scanString:@":" intoString:NULL]) {
[scanner scanCharactersFromSet:mimeTypeSet intoString:&mimeType];
}
GHAssertEqualStrings(@"application/xml", mimeType, @"Mime-type should be application/xml");
// Prepare to look for the charset attribute
NSString *charset = nil;
// Ignore quotes as well as whitespace
[scanner setCharactersToBeSkipped:[NSCharacterSet characterSetWithCharactersInString:@"\r\n\t \""]];
// Skip past the charset attribute declaration
if ([scanner scanUpToString:@"charset=" intoString:NULL]
&& [scanner scanString:@"charset=" intoString:NULL]) {
[scanner scanCharactersFromSet:charsetSet intoString:&charset];
}
GHAssertEqualStrings(@"utf-8", charset, @"Charset should be utf-8");
}通过使用while循环读取到";“然后检查是否是我正在扫描的属性,这可能会变得更聪明一些。
我敢说,它比使用regex更快地进行了基准测试,而且我相当长的代码可以重构成更小的代码。
发布于 2010-05-26 08:36:12
如果这些是,从技术上讲,根据我对RFC2616的阅读,第二个标题是非法的。你不能引用字符集的名字。尽管如此,你不能控制你的输入,如果你得到它们,你需要处理它们。
无论如何,假设我们讨论的是HTTP头,即使我手头有一个regex库,我也很想编写一个适当的解析器。假设您想有点懒,没有regex库或解析器,您需要这样做:
mime类型是前导和尾随空格的第一部分。
现在出现了棘手的部分。遍历剩余的每个组件。
charset (不区分大小写),您已经找到了要查找的部分。第二部分是实际字符集-条形空格和包围双引号.上面的情况很复杂,而且可能会有失败的边缘情况,但是您创建的任何正则表达式也会很复杂,有边缘情况失败,无法读,并且不可能用Xcode调试器进行调试。
发布于 2010-05-26 05:04:54
我觉得你应该顺应你的本能。使用RegexKitLite。这是非常小和简单的添加到这个项目。
另一个选项,如果这是用于iPhone或iPad使用iPhone OS3.2,则可以在-rangeOfCharacterFromSet:options:中使用新的NSRegularExpressionSearch选项。
但是,如果我不使用正则表达式,就会有一系列indexOf、rangeOf和子字符串调用。它可能只有六行,但仍然没有正则表达式那么简单和漂亮。
https://stackoverflow.com/questions/2910120
复制相似问题