首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >从NSString中提取已知的模式子字符串(没有正则表达式)

从NSString中提取已知的模式子字符串(没有正则表达式)
EN

Stack Overflow用户
提问于 2010-05-26 04:49:57
回答 2查看 2.2K关注 0票数 0

我真的很想把RegexKit (或者我自己的libpcre包装器)放到我的项目中去,但是在我这么做之前,我想知道Cocoa开发人员是如何在没有真正复杂的代码或者没有与RegexKit或其他正则表达式库链接的情况下完成这些基本内容的。

我发现Cocoa不包含任何正则表达式匹配特性,这让人目瞪口呆。我已经习惯于将正则表达式用于所有类型的事情,没有正则表达式我就会迷失方向。没有它们,我可以做我需要的事情,但是代码会相当复杂。所以,可可神,我问你,“可可之路”是怎么做的.

就我而言,这个问题是编程中的一个日常问题。可可必须有办法用内置的功能来做到这一点。注意,我想匹配的元素的位置会发生变化,有时还会出现“引号”。空白是可变的。

以下列字符串为例:

代码语言:javascript
复制
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实例中最烦人的部分。

代码语言:javascript
复制
- (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更快地进行了基准测试,而且我相当长的代码可以重构成更小的代码。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2010-05-26 08:36:12

如果这些是,从技术上讲,根据我对RFC2616的阅读,第二个标题是非法的。你不能引用字符集的名字。尽管如此,你不能控制你的输入,如果你得到它们,你需要处理它们。

无论如何,假设我们讨论的是HTTP头,即使我手头有一个regex库,我也很想编写一个适当的解析器。假设您想有点懒,没有regex库或解析器,您需要这样做:

  • 带“内容长度:”。
  • 使用-componentsSeparatedByString:在分号处拆分。

mime类型是前导和尾随空格的第一部分。

现在出现了棘手的部分。遍历剩余的每个组件。

  • 对于您所在的部分,请确保拆分的分号没有嵌入到字符串中。最简单的方法是计算未转义双引号字符的数量,并确保零或两个。如果yuou确实在引号上拆分,请重新加入下一个组件并重复。
  • 在=符号处分裂
  • 如果第一部分是charset (不区分大小写),您已经找到了要查找的部分。第二部分是实际字符集-条形空格和包围双引号.

上面的情况很复杂,而且可能会有失败的边缘情况,但是您创建的任何正则表达式也会很复杂,有边缘情况失败,无法读,并且不可能用Xcode调试器进行调试。

票数 1
EN

Stack Overflow用户

发布于 2010-05-26 05:04:54

我觉得你应该顺应你的本能。使用RegexKitLite。这是非常小和简单的添加到这个项目。

另一个选项,如果这是用于iPhone或iPad使用iPhone OS3.2,则可以在-rangeOfCharacterFromSet:options:中使用新的NSRegularExpressionSearch选项。

但是,如果我不使用正则表达式,就会有一系列indexOf、rangeOf和子字符串调用。它可能只有六行,但仍然没有正则表达式那么简单和漂亮。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/2910120

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档