【问题标题】:Regular Expression for specific requirements特定要求的正则表达式
【发布时间】:2016-11-19 09:26:55
【问题描述】:

以下是我的字符串集合,指的是从头到尾的路径,像ABC这样的每个元素都是一个城市终端:

"ABC-DEF-MNO-JKL-LOO"
"BYT-JKU-PLO-MNO"
"DEF-BYT-IOT-POC-LOO"
"LMN-RTX-PQS-JYY"
"LMN-PQS-IRJ"

我开发了以下正则表达式模式来满足业务需求:

要求1 - Start with ABC or DEF, pass via MNO or BYT, End with LOO,JYY,IRJ

Pattern 1 - `@"(^ABC|^DEF).*(MNO|BYT).*(LOO$|JYY$|IRJ$)";`
Result 1 - "ABC-DEF-MNO-JKL-LOO", "DEF-BYT-IOT-POC-LOO"

要求2 - Start with ABC or DEF, pass via MNO or BYT, exclude route with IOT and End with LOO,JYY,IRJ

 Expected Result - "ABC-DEF-MNO-JKL-LOO", since the other route has IOT

Expected Pattern - `@"(^ABC|^DEF).*(MNO|BYT).*^(IOT).*(LOO$|JYY$|IRJ$)";`

但是这个没有提供任何结果

Successful Pattern - `@"(^ABC|^DEF).*(MNO|BYT.*^(IOT)).*(LOO$|JYY$|IRJ$)";`

但是我不相信,这是实现它的正确方法,任何人都可以帮助理解:

  • 为什么预期模式无助于产生正确的结果,我不明白其中有什么问题
  • 建议更好的正则表达式来达到相同的结果

编辑 1:

根据@Sebastian 提供的响应,以下模式也成功:

@"^(?:ABC|DEF).*(?:MNO|BYT)(?!.*IOT).*(?:LOO|JYY|IRJ)$"

但以下模式失败,当只有额外的.*

@"^(?:ABC|DEF).*(?:MNO|BYT).*(?!.*IOT).*(?:LOO|JYY|IRJ)$"

【问题讨论】:

    标签: c# .net regex pattern-matching


    【解决方案1】:

    您可以使用^(?:ABC|DEF)(?!.*IOT).*(?:MNO|BYT).*(?:LOO|JYY|IRJ)$ 来满足您的第二个要求。如果存在IOT,这将使用negative lookahead 来避免匹配。其余部分取自您的模式,只是使组不捕获并将锚点移动到组之外。

    您的伪成功模式使用以下(MNO|BYT.*^(IOT)) 匹配MNOBYT.*^(IOT),因此如果您的字符串中存在MNO,则不会检查IOT。此外,^(IOT) 匹配字符串的开头 + IOT,它永远不会出现在字符串中。

    【讨论】:

    • 这导致正确答案,但我不明白,你为什么要把^(?!.*IOT)放在开头,为什么不按照里面的逻辑呢
    • 请根据您的回复检查编辑,是否意味着^(?!.*IOT)的位置无关,可以在任何地方
    • @MrinalKamboj 你应该对lookarounds 做一些研究,(?!.*IOT) 是一个否定的lookahead,因此断言里面的东西是不匹配的。因此,它应该尽可能早地出现并在需要时出现。请注意,您在编辑中的第一个模式将匹配 ABC-MNO-IOT-BYT-IRJ
    • 当然谢谢,所以按照你的说法,我们最好把它放在开头做断言
    • @MrinalKamboj 这在很大程度上取决于实际需求。如果某个子字符串不应该出现在任何地方(如您的情况),那么是的。
    【解决方案2】:

    以 ABC 或 DEF 开头:^(?:ABC|DEF)-

    通过 MNO 或 BYT:(?:MNO|BYT)-

    使用 IOT 排除路由:(?!IOT)-

    并以 LOO,JYY,IRJ 结尾:(?:LOO|JYY|IRJ)$

    把它们放在一起:

    ^(?:ABC|DEF)-(?:(?!IOT)[A-Z]{3}-)*?(?:MNO|BYT)-(?:(?!IOT)[A-Z]{3}-)*(?:LOO|JYY|IRJ)$
    

    【讨论】:

    • 感谢它非常合乎逻辑的理解,我尝试了修改后的用法以增加我的用例的灵活性:^(?:ABC|DEF)(?!.*IOT).*(?:MNO|BYT)(?!.*IOT).*(?:LOO|JYY|IRJ)$
    • @MrinalKamboj 如果灵活性是目标,请参阅 Sebastian 的回答,如果您在前瞻中使用 .*,那么拥有一次就足够了。如果你想允许更多的字母,比如说 2-4,那么你在重复中这样做{2,4}
    • 当您输入 {3,4} 时,RIOT 将是一个有效的机场......但 IOTA 不是,因此如果 IOTA 应该是一个有效的机场并且只有物联网应该被阻止,灵活的版本也是如此。
    • 在上面的版本中,您可以对IOT- 进行前瞻来纠正这个问题,在灵活的版本.*-IOT- 中。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-05-06
    • 2015-03-23
    相关资源
    最近更新 更多