如何使用正则表达式和NSPredicate搜索时忽略特定字符?

11
在希伯来语中,即使在谓词中使用“d”(音标不敏感)修饰符,某些元音字母仍然无法被NSPredicate忽略。我被告知解决办法是使用正则表达式进行搜索。
如何使用正则表达式搜索包含元音字母的希伯来文本,并忽略这些元音字母?
编辑:换句话说,如果我想搜索以下文本,忽略破折号和星号,我该如何使用正则表达式进行搜索?
示例文本:
"I w-en*t t-o the st*o*r*-e yes-ster*day."
编辑2:基本上,我想要:
1. 从用户获取输入字符串 2. 取一个字符串进行搜索 3. 根据用户的搜索字符串使用正则表达式在较大的文本块中搜索“包含”匹配项。正则表达式应该像上面那样忽略元音字母。
编辑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]?

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

而且,我需要剩下的正则表达式不区分大小写。我需要在.*正则表达式中使用哪个修饰符来使其不区分大小写?


可能是NSPredicate和Regex的重复问题。 - 一二三
可能会:1. 删除不良符号(元音)。2. 在每个字符后面添加类似于“.*?”的内容。3. 搜索。您是否接受这样的决定? - Nekto
2个回答

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];
  }          
}

请注意,正则表达式的范围部分会重复出现。这是因为单个字母上可能既有歌唱符号又有元音符号。现在,我可以搜索带或不带元音符和歌唱符的大写和小写英语以及希伯来语。
太棒了!

很高兴你找到了答案。我没有意识到你也在搜索英文文本或带有唱诵符号的希伯来语。话虽如此,我有一种感觉你没有100%的解决方案。例如,考虑这个经文“על פני המים”。字母“מ”有一个元音标记和一个dagesh。这是3个,但你只允许2个。另外,我不确定以元音字母开头的字符串是否有效的Unicode,但如果是,你也没有去掉它。 - JXG
好的观点。您认为在正则表达式字符串中添加第三个字符值得吗?有没有一种方法可以指定“零个或多个,最多三次”? - Moshe
我建议仍然使用 *,但是我认为 {0,3} 也可以用于0到3次之间的匹配,但不确定是否可以在 {} 中使用0。 - JXG

2
希伯来语元音在Unicode中定义得很好:希伯来字符和标记表
当你从用户那里收到输入字符串时,可以在每个字符之间以及字符串前后插入正则表达式[\u05B0-\u05C4]*。([]表示匹配任何包含的字符,*表示匹配表达式的零个或多个出现。)然后,您可以使用这个作为正则表达式搜索文本块。该表达式允许您找到用户输入的精确字符串。用户还可以指定所需的元音,该表达式将找到这些元音。
我认为,与其试图“忽略”元音,不如从大块文本和用户字符串中删除元音,然后像通常一样仅搜索字母。如果您不需要显示用户找到的带声调文本,则此方法将起作用。

看起来是个好主意。将搜索字符串转换为正则表达式的有效方法是什么? - Moshe
@Moshe,我不知道一个有效(或者甚至是好的)方法是什么。你可以使用NSMutableStringinsertString:atIndex:,我想在循环内从字符串的末尾开始递减计数。但我不确定那是否非常好。 - JXG
我已经有一个可行的解决方案了,这很有帮助,在我到达电脑时会有更多的内容。 - Moshe
你帮助我找到了答案,谢谢!奖励归你! - Moshe

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接