在macOS上的二进制数据内不区分大小写的文本搜索

时间:2019-04-27 21:15:47

标签: macos

我正在尝试实现第三种功能,以在无法加载到NSString中的文件中查找文本。

这适用于通用二进制文件,但也适用于具有非Unicode编码的有效文本文件,我无法预测其编码,例如ISO Latin或MacRoman。

我想搜索用户可以在NSTextField中输入的任何文本,这意味着我希望能够找到任何语言和脚本形式的有效Unicode文本。

我唯一的假设是我要查找的文本使用的是UTF-8编码(即,我不需要处理UTF-16)。如果文件实际上是MacRoman编码的,而我搜索的是非ASCII字符(第8位),则不需要查找匹配项。

我在这里尝试解决的问题是NSString无法加载某些“错误”编码的文件,我仍然希望在错误字符周围找到任何东西。

搜索应该对以下内容不敏感:

  • 案例(最高优先级)
  • 变音符号(低优先级)
  • unicode组成(低优先级)

另一个目标是要快。这是一个文件搜索实用程序,它可能会查看数千个大型文件。

由于无法将数据加载到NSString中,因此必须使用其他搜索API。

我有什么选择?是否有图书馆可以做到这一点,即查找文本,跳过不良字符?

(我以为我可以使用系统提供的regex函数,但也可以使用run into a problem,尽管那并不那么严重)。


注意:我尝试使用以下方法将此类数据转换为NSString

[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding]

[NSString stringEncodingForData:data encodingOptions:@{
        NSStringEncodingDetectionAllowLossyKey: @YES,
        NSStringEncodingDetectionLossySubstitutionKey: @" ",
        NSStringEncodingDetectionUseOnlySuggestedEncodingsKey: @YES,
        NSStringEncodingDetectionSuggestedEncodingsKey: @[@(NSASCIIStringEncoding)]
    }
    convertedString:&text usedLossyConversion:nil
];

虽然两者似乎一开始都是可行的,但是一旦我调用-[NSString localizedStandardContainsString]和类似的搜索功能,这会导致偶尔的内核崩溃或其他严重崩溃。但是,当它没有崩溃时,它会很好地工作。

这些崩溃出现在我的10.13.6上,这足以让我避免使用该技术,即使Apple可能已在10.14.3中修复了此问题。

1 个答案:

答案 0 :(得分:0)

我想出了一个不太优雅的解决方案,可能效率很低。

我正在尝试使用系统提供的正则表达式库。这样做的问题是,NSString的find操作不能很好地处理各种事情:

  • 它们不是标准化专家,也就是说,如果我搜索预组合(NFC)字符,则在目标数据中如果它以分解(NFD)形式出现,则找不到字符。
  • 不区分大小写的搜索不适用于拉丁文NFC字符(搜索Ü找不到ü),而仅适用于ASCII字母(a-z)。

我认为,通过使用诸如Aho–Corasick之类的智能搜索算法,可以生成考虑了非ASCII字符的每个变体的精通Unicode的搜索树。但是事实并非如此。

因此,我认为我可以通过构建一个正则表达式搜索字符串来将所有这些变体形式化,以正则表达式来帮助它们,并以|隔开。

我可以验证此算法是否适用于拉丁字符,但不知道它是否也可以与其他脚本(例如中文)一起使用,我相信其中也存在规范化变化。

代码很长,因此我将在此处总结算法。我已经发布了code here

  • 我将搜索字符串转换为NFC形式。
  • 我查看搜索字符串中的每个字符。
  • 如果char的代码是<128,则保持这种方式。
  • 测试了
  • Char> = 128是否具有不同的大写/小写表示形式。如果是这样,我将为每个创建两个替代搜索字符串。
  • 我最终得到了一个或多个搜索字符串。
  • 现在,我将每个搜索字符串转换为NFC和NFD形式,从而增加了更多的变化形式。
  • 最后,我转义了要与正则表达式一起使用的每个字符串,并将它们全部用“ |”连接起来作为分隔符。

例如,使用NFC和NFD表示形式,将带有ä和Ä的搜索字符串ä转换为\ä|\Ä|\ä|\Ä。二进制形式的字符串如下所示:

5C C3 A4 7C 5C C3 84 7C 5C 61 CC 88 7C 5C 41 CC 88