NSRegularExpression查找带有可选部分的模式

时间:2013-05-21 08:55:31

标签: objective-c regex nsregularexpression

事情就是这样:

我有一个存储一些数据的文件,遵循以下模式:

item1:value1 item2:value2 item3:value3 // \n
item1:value1 item2:value2
item1:value1 item2:value2
// and so on...

// item3:value3 IS OPTIONAL

然后我将文件的数据存储在NSString中,以便处理它们。

我想匹配value2,但问题是每行item3:value3的必要性是可选的。

所以我尝试使用?正则表达式运算符,但我不确定使用它的方法。

所以我通常尝试匹配以下模式(不起作用,ofc):

@"item1:.* item2:(.*) (item3:.*)?\n"

更好的解释,我想重新组合1中的2个条件:

@"item1:.* item2:(.*) item3:.*\n" // Case 1 : item3:.* present in the line
@"item1:.* item2:(.*)\n"          // Case 2 : item3 not present

请注意,我已经创建了一个personnal函数,它返回NSMutableArray中的所有匹配项。

我希望这很清楚:/

感谢您的帮助和想法。

2 个答案:

答案 0 :(得分:1)

好吧,看起来这个正则表达式中有一些错误:我现在将完成它们。

首先,您尝试将行尾与“\ n”匹配。如果你的字符串以新行结束,但是与最后一行不匹配,这将正常工作。要解决此问题,请使用“$”符号,并确保在实例化正则表达式时将NSRegularExpressionAnchorsMatchLines作为options:参数传递,例如:

NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:@"item1:.* item2:(.*?)(?: item3:.*)?$"
                                                  options:NSRegularExpressionAnchorsMatchLines
                                                  error:nil];

$符号称为锚点,默认情况下匹配字符串的结尾。它的对面是^锚,它匹配字符串的开头。但是,如果传递NSRegularExpressionAnchorsMatchLines选项,这些锚点会更改行为以匹配字符串任何行的开头和结尾。

其次,您正在使用平面parethensis ()来对“item3:”部分进行分组,但您不希望因匹配而将该组取出(“捕获”) 。如果您不想“捕获”组中的文本,请编写类似(?:...)的组。严格地说,使用平面括号将起作用(并且在您的示例中),但意味着正则表达式引擎必须执行更多工作,因为它需要跟踪捕获组内的内容,以便您可以在方法返回时访问它(在您的情况下使用rangeAtIndex:2)。

第三,你错误地放置了正则表达式中的空格(就在item3组的左括号之前),这样如果item2的数据在空格中结束或者行有item3,那么你的正则表达式只匹配一行条目。这就好像?似乎没有在你的正则表达式中工作,并且会自己解决你的主要问题。空格需要位于问号后面的组内,否则只有空格实际存在时才会匹配正则表达式!

最后:*运算符默认为 greedy ,这意味着它将尽可能多地匹配。这会使正则表达式的(.*)部分占用所有文本直到行尾,并且正则表达式仍将匹配,因为(item3:.*)?部分是可选的。在?之后放置*(即.*?)会更改*的工作方式,使其 lazy 以便与之匹配尽可能使用文本,这意味着,如果可能,正则表达式更倾向于将行的item3部分与正则表达式的(item3:.*)?部分上的正则表达式的item2:(.*)部分进行匹配。

所以你的正则表达式如下:

@"item1:.* item2:(.*?)(?: item3:.*)?$"

答案 1 :(得分:0)

因此,如果您在文本中具有可靠的一致模式,则可以分析模式以构建正则表达式和Objective-C逻辑。

首先确定可靠地分离您感兴趣的元素的子字符串。 假设粘贴的是什么, 首先,您可以通过新行分隔符分隔每个项目。 制作一系列线条。如果每个系列的编号项以某种方式相关,则这很有用。

接下来,根据您粘贴的内容,您可能有多种方法来识别您感兴趣的每一行的部分。

同样,你真的需要简单地了解你的字符串中可能包含的内容以及不在其中的内容。

当且仅当项目本身不包含空格时,您才可以使用空格来进一步标识单独的项目。 如果您只能验证项目的定义是这样的,那么您需要做一些工作: 定义: item是紧跟在带有模式的字符串后面的字符串: 行的开头或单个空格后跟“item”后跟数字1,2或3,后跟“:”

值字符串的结尾由行尾或分隔符开始另一个项目分隔。

从这里你应该能够用正则表达式替换模式的定义。

如果使用编程语言逻辑和条件将其分解为多个步骤,并且不尝试在单个正则表达式中执行所有操作,那么您将有更轻松的时间。

相关问题