如何使用正则表达式搜索忽略 NSPredicate 的某些字符?
Posted
技术标签:
【中文标题】如何使用正则表达式搜索忽略 NSPredicate 的某些字符?【英文标题】:How do I use regex to search ignoring certain characters with NSPredicate? 【发布时间】:2011-11-07 03:26:00 【问题描述】:在希伯来语中,NSPredicate 无法忽略某些元音,即使在谓词中使用“d”(变音符号不敏感)修饰符也是如此。有人告诉我,解决方案是使用正则表达式进行搜索。
如何获取搜索字符串并“使用正则表达式”来搜索包含元音的希伯来文文本,而忽略这些元音?
编辑:
换句话说,如果我想搜索以下文本,不考虑破折号和星号,我将如何使用正则表达式?
示例文字:
我 w-en*t t-o st*o*r*-e yes-ster*day。
编辑 2:
基本上,我想:
-
从用户那里获取输入字符串
取一个字符串进行搜索
使用基于用户搜索字符串的正则表达式在较大的文本块中搜索“包含”匹配项。正则表达式应忽略元音,如上所示。
编辑 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 and Regex的可能重复 可能是: 1. 删除坏符号(元音)。 2. 添加类似这样的内容:“.*?”在每个字符之后。 3. 搜索。你会接受这样的决定吗? 【参考方案1】:希伯来语元音在 Unicode 中定义明确:Table of Hebrew characters and Marks
当您收到用户输入的字符串时,您可以在每个字符之间以及字符串的前后插入正则表达式[\u05B0-\u05C4]*
。 ([]
表示匹配任何包含的字符,*
表示匹配零次或多次出现的表达式。)然后您可以搜索文本块,将其用作正则表达式。此表达式允许您从用户输入中找到确切的字符串。用户还可以指定所需的元音,该表达式会找到这些元音。
我认为与其尝试“忽略”元音,不如从大文本块和用户字符串中删除元音会更容易。然后你可以像往常一样只搜索字母。如果您不需要显示用户找到的有声文本,则此方法会起作用。
【讨论】:
看起来是个好主意。将搜索字符串转换为正则表达式的有效方法是什么? @Moshe,我不知道什么是有效(甚至是好)的方法。您可以使用NSMutableString
和insertString:atIndex:
,我想从字符串末尾开始循环倒计时。不过,我不知道这是否很好。
我有一个可行的解决方案,这很有帮助,当我在电脑前时会有更多。
你引导我找到我自己的答案,有赏金!【参考方案2】:
这个答案从问题停止的地方开始。请阅读上下文。
事实证明,ios 可以使用 NSPredicate 的 Objective-C 修饰符使正则表达式不区分大小写。剩下的就是结合这两个范围。我意识到它们实际上是两个连续的范围。我的最终代码如下所示:
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];
请注意,正则表达式的范围部分会重复。这是因为单个字母上可以同时有一个cantillation mark 和一个元音。现在,我可以搜索大写和小写的英语,以及带有或不带有元音和音标的希伯来语。
太棒了!
【讨论】:
很高兴您找到了答案。我没有意识到您也在搜索英文文本或带有cantillation 的希伯来文。也就是说,我感觉您没有 100% 的解决方案。举个例子诗句 על פני המים。 “מ”有元音、标记和达格什。那是 3,但你只允许 2。另外,我不确定以元音开头的字符串是否是有效的 Unicode,但如果是,你不要去掉它。 好点。您认为值得在正则表达式字符串中添加第三个字符吗?有没有办法指定“零次或多次,最多三次”? 我建议像以前一样使用*
,但我认为0,3
也可以工作0 到3 次——不确定你是否可以将0 与
一起使用。跨度>
以上是关于如何使用正则表达式搜索忽略 NSPredicate 的某些字符?的主要内容,如果未能解决你的问题,请参考以下文章