如何使用正则表达式搜索使用NSPredicate忽略某些字符?

时间:2011-11-07 03:26:00

标签: objective-c ios regex search nspredicate

在希伯来语中,即使在谓词中使用“d”(变音符号不敏感)修饰符,NSPredicate仍然会忽略某些元音。我被告知解决方案是使用正则表达式进行搜索。

如何使用搜索字符串和“使用正则表达式”搜索包含元音的希伯来文本,忽略这些元音?

修改

换句话说,如果我想搜索以下文本,忽略破折号和星号,我将如何使用正则表达式?

示例文字:

  

我w-en * t t o o st * o * r * -e yes-ster * day。

编辑2:

基本上,我想:

  1. 从用户那里获取输入字符串
  2. 用字符串搜索
  3. 使用基于用户搜索字符串的正则表达式在较大的文本块中搜索“包含”匹配项。正则表达式应该忽略如上所示的元音。
  4. 编辑3:

    以下是我实施搜索的方式:

    //
    //  The user updated the search text
    //
    
    - (BOOL)searchDisplayController:(UISearchDisplayController *)controller 
    shouldReloadTableForSearchString:(NSString *)searchString{
    
        NSMutableArray *unfilteredResults = [[[[self.fetchedResultsController sections] objectAtIndex:0] objects] mutableCopy];
    
        if (self.filteredArray == nil) {
            self.filteredArray = [[[NSMutableArray alloc ] init] autorelease];
        }
    
        [filteredArray removeAllObjects];
    
        NSPredicate *predicate;
    
        if (controller.searchBar.selectedScopeButtonIndex == 0) {
            predicate = [NSPredicate predicateWithFormat:@"articleTitle CONTAINS[cd] %@", searchString];
        }else if (controller.searchBar.selectedScopeButtonIndex == 1) {
            predicate = [NSPredicate predicateWithFormat:@"articleContent CONTAINS[cd] %@", searchString];            
        }else if (controller.searchBar.selectedScopeButtonIndex == 2){
            predicate = [NSPredicate predicateWithFormat:@"ANY tags.tagText CONTAINS[cd] %@", searchString];
        }else{
            predicate = [NSPredicate predicateWithFormat:@"(ANY tags.tagText CONTAINS[cd] %@) OR (dvarTorahTitle CONTAINS[cd] %@) OR (dvarTorahContent CONTAINS[cd] %@)", searchString,searchString,searchString];
        }
    
        for (Article *article in unfilteredResults) {
    
            if ([predicate evaluateWithObject:article]) {
                [self.filteredArray addObject:article];
            }
    
        }
    
        [unfilteredResults release];
    
    
        return YES;
    }
    

    编辑4:

    我不需要使用正则表达式,只是建议这样做。如果你有另一种方法可行,那就去吧!

    编辑5:

    我将搜索修改为如下所示:

    NSInteger length = [searchString length];
    
    NSString *vowelsAsRegex = @"[\\u5B0-\\u55C4]*";
    
    NSMutableString *modifiedSearchString = [searchString mutableCopy];
    
    for (int i = length; i > 0; i--) {
        [modifiedSearchString insertString:vowelsAsRegex atIndex:i];
    }
    
    if (controller.searchBar.selectedScopeButtonIndex == 0) {
                predicate = [NSPredicate predicateWithFormat:@"articleTitle CONTAINS[cd] %@", modifiedSearchString];
            }else if (controller.searchBar.selectedScopeButtonIndex == 1) {
                predicate = [NSPredicate predicateWithFormat:@"articleContent CONTAINS[cd] %@", modifiedSearchString];            
            }else if (controller.searchBar.selectedScopeButtonIndex == 2){
                predicate = [NSPredicate predicateWithFormat:@"ANY tags.tagText CONTAINS[cd] %@", modifiedSearchString];
            }else{
                predicate = [NSPredicate predicateWithFormat:@"(ANY tags.tagText CONTAINS[cd] %@) OR (dvarTorahTitle CONTAINS[cd] %@) OR (dvarTorahContent CONTAINS[cd] %@)", modifiedSearchString,modifiedSearchString,modifiedSearchString];
            }
    
    for (Article *article in unfilteredResults) {
      if ([predicate evaluateWithObject:article]) {
        [self.filteredArray addObject:article];
      }          
     }
    

    我在这里仍然遗漏了一些东西,我需要做些什么来完成这项工作?

    编辑6:

    好的,几乎就在那里。我需要再做两次更改才能完成。

    我需要能够为正则表达式添加其他范围的字符,这可能会出现,而不是另一组中的字符。我试图将第一个范围更改为:

    [\u05b0-\u05c, \u0591-\u05AF]?
    

    有些东西告诉我这是不正确的。

    另外,我需要其余的正则表达式不区分大小写。我需要使用什么修饰符与.*正则表达式使其不区分大小写?

2 个答案:

答案 0 :(得分:2)

希伯来语元音在Unicode中得到了很好的定义:Table of Hebrew characters and Marks

当您收到用户的输入字符串时,您可以在每个字符之间以及字符串之前和之后插入正则表达式[\u05B0-\u05C4]*。 ([]表示匹配任何包含的字符,*表示匹配零个或多个表达式。)然后,您可以搜索文本块,将其用作正则表达式。此表达式允许您从用户的输入中查找确切的字符串。用户还可以指定此表达式可以找到的所需元音。

我认为不要试图忽略"在元音中,从大块文本和用户字符串中删除元音会更容易。然后你可以照常搜索字母。如果您不需要显示用户找到的发声文本,此方法就可以使用。

答案 1 :(得分:2)

这个答案可以解决问题所在。请阅读上下文。

事实证明,iOS可以使用Objective-C修饰符对NSPredicate使正则表达式不区分大小写。剩下的就是将两个范围结合起来。我意识到它们实际上是两个连续的范围。我的最终代码如下所示:

NSInteger length = [searchString length];

NSString *vowelsAsRegex = @"[\u0591-\u05c4]?[\u0591-\u05c4]?"; //Cantillation: \u0591-\u05AF Vowels: \u05b0-\u05c

NSMutableString *modifiedSearchString = [searchString mutableCopy];

for (int i = length; i > 0; i--) {
    [modifiedSearchString insertString:vowelsAsRegex atIndex:i];
}

if (controller.searchBar.selectedScopeButtonIndex == 0) {
  predicate = [NSPredicate predicateWithFormat:@"articleTitle CONTAINS[cd] %@", modifiedSearchString];
}else if (controller.searchBar.selectedScopeButtonIndex == 1) {
    predicate = [NSPredicate predicateWithFormat:@"articleContent CONTAINS[c] %@", modifiedSearchString];            
}else if (controller.searchBar.selectedScopeButtonIndex == 2){
    predicate = [NSPredicate predicateWithFormat:@"ANY tags.tagText CONTAINS[c] %@", modifiedSearchString];
}else{
    predicate = [NSPredicate predicateWithFormat:@"(ANY tags.tagText CONTAINS[c] %@) OR (dvarTorahTitle CONTAINS[c] %@) OR (dvarTorahContent CONTAINS[c] %@)", modifiedSearchString,modifiedSearchString,modifiedSearchString];
}

[modifiedSearchString release];

for (Article *article in unfilteredResults) {
  if ([predicate evaluateWithObject:article]) {
    [self.filteredArray addObject:article];
  }          
}

请注意,正则表达式的范围部分会重复。这是因为单个字母上既可以有旋转标记,也可以有元音。现在,我可以搜索大写和小写的英语和希伯来语,有或没有元音和标记。

真棒!