【问题标题】:NSRegularExpression find pattern with optional partNSRegularExpression 查找带有可选部分的模式
【发布时间】:2013-05-21 18:52:03
【问题描述】:

事情是这样的:

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

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

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

我希望这已经足够清楚了:/

感谢您的帮助和想法。

【问题讨论】:

    标签: objective-c regex nsregularexpression


    【解决方案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:.*)? 部分是可选的。在* 之后放置?(即.*?)会改变* 的工作方式,使其惰性 匹配尽可能少的文本,这意味着,如果可能的情况下,正则表达式会优先匹配行的 item3 部分与正则表达式的 (item3:.*)? 部分,而不是正则表达式的 item2:(.*) 部分。

    所以你的正则表达式看起来像:

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

    【讨论】:

    • 对不起,我放错地方了。试试看。我是否正确理解您的问题是您只希望返回 item2 的值,而不是其他任何东西,但您的尝试返回太多?
    • 我想在以下情况下匹配 item2:1. item3 存在 2. item3 不存在 因为 item3 是可选的,所以它可以在这里或不存在! :)
    • 当你尝试上面的正则表达式会发生什么?不匹配吗?
    • 它返回最后一个匹配:D
    • 笑脸是否表明这是您想要的,还是您想要每场比赛?返回最后一个匹配是正则表达式的结果,还是您正在使用的方法?
    【解决方案2】:

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

    首先确定能够可靠地分隔您感兴趣的元素的子字符串。 假设从粘贴的内容来看, 首先,您可以用换行符分隔每个项目。 制作一系列线条。如果每个编号的项目系列都以某种方式相关,这将很有用。

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

    同样,您确实需要简单地了解您的字符串中可能包含哪些内容以及其中不包含哪些内容。

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

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

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

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

    【讨论】:

    • 我已经考虑过了,但我更喜欢尝试使用 RegEx 和NSRegularExpressionclass,因为我知道这些工具中有很多我还不知道的强大功能。而且我知道我的方式会比我使用这些工具更重。
    猜你喜欢
    • 2015-01-11
    • 2012-05-10
    • 1970-01-01
    • 2017-02-21
    • 2016-01-10
    • 2012-05-30
    • 2015-06-09
    • 1970-01-01
    • 2011-10-31
    相关资源
    最近更新 更多