仅当字符串的一部分前面没有某些字符时,如何匹配它?

Posted

技术标签:

【中文标题】仅当字符串的一部分前面没有某些字符时,如何匹配它?【英文标题】:How do I match part of a string only if it is not preceded by certain characters? 【发布时间】:2010-09-17 11:03:33 【问题描述】:

我创建了以下正则表达式模式,以尝试匹配以“PRI”或“SEC”结尾的长度为 6 个字符的字符串,除非字符串 =“SIGSEC”。例如,我想匹配 ABCPRI、XYZPRI、ABCSEC 和 XYZSEC,而不是 SIGSEC。

(\w3PRI$|[^SIG].*SEC$)

它非常接近并且有点工作(如果我传入“SINSEC”,它会返回“NSEC”的部分匹配),但我对它目前的形式感觉不太好。此外,我以后可能需要添加除“SIG”之外的更多排除项,并意识到这可能不会很好地扩展。有什么想法吗?

顺便说一句,我在 C# 中使用 System.Text.RegularExpressions.Regex.Match()

谢谢, 丰富

【问题讨论】:

【参考方案1】:

假设您的正则表达式引擎支持负前瞻,试试这个:

((?!SIGSEC)\w3(?:SEC|PRI))

编辑:一位评论者指出 .NET 确实支持负前瞻,所以这应该可以正常工作(感谢 Charlie)。

【讨论】:

.NET 正则表达式确实支持负前瞻,所以这会起作用 啊,很高兴知道,谢谢查理。我真的不是 .NET 人 ;) 这很好用,丹,谢谢!运行一个快速测试,添加额外的排除匹配将是微不足道的。 附带说明,.Net 正则表达式支持各种环视的无限长度环视。实际上 .Net 正则表达式和 JGsoft 引擎是唯一允许“在后向内查看完整正则表达式”的正则表达式引擎【参考方案2】:

为了帮助分解 Dan 的(正确)答案,它的工作原理如下:

(           // outer capturing group to bind everything
 (?!SIGSEC) // negative lookahead: a match only works if "SIGSEC" does not appear next
 \w3      // exactly three "word" characters
 (?:        // non-capturing group - we don't care which of the following things matched
   SEC|PRI  // either "SEC" or "PRI"
 )
)

一起:((?!SIGSEC)\w3(?:SEC|PRI))

【讨论】:

【参考方案3】:

你可以试试这个:

@"\w3(?:PRI|(?<!SIG)SEC)"
匹配 3 个“单词”字符 匹配 PRI 或 SEC(但不是在 SIG 之后,即排除 SIGSEC)(?

另外,我可能需要添加更多内容 以后除“SIG”之外的排除和 意识到这可能无法扩展 太好了

使用我的代码,您可以轻松添加其他异常,例如以下代码排除 SIGSEC 和 FOOSEC

@"\w3(?:PRI|(?<!SIG|FOO)SEC)"

【讨论】:

【参考方案4】:

为什么不使用更具可读性的代码?在我看来,这更易于维护。

private Boolean HasValidEnding(String input)

    if (input.EndsWith("SEC",StringComparison.Ordinal) || input.EndsWith("PRI",StringComparison.Ordinal))
    
        if (!input.Equals("SIGSEC",StringComparison.Ordinal))
        
            return true;
        
    
    return false;

或一行

private Boolean HasValidEnding(String input)

    return (input.EndsWith("SEC",StringComparison.Ordinal) || input.EndsWith("PRI",StringComparison.Ordinal)) && !input.Equals("SIGSEC",StringComparison.Ordinal);

不是我不使用正则表达式,而是在这种情况下我不会使用它们。

【讨论】:

是的,我实际上是从完全按照这些思路开始的,但需求发生了变化,我决定将逻辑外部化。我选择在配置文件中使用正则表达式,以便在需要添加新的排除字符串时不必更改代码。【参考方案5】:

就个人而言,我倾向于使用第二个变量来构建排除列表,然后将其包含到完整的表达式中 - 这是我过去在构建时使用的方法 any em> 复杂的表达式。

类似exclude = 'someexpression'; prefix = 'list of prefixes'; suffix = 'list of suffixes'; expression = 'prefixexcludesuffix';

【讨论】:

【参考方案6】:

您甚至可能不想在正则表达式中进行排除。例如,如果这是 Perl(我不懂 C#,但你可能可以跟着学),我会这样做

if ( ( $str =~ /^\w3(?:PRI|SEC)$/ ) && ( $str ne 'SIGSEC' ) )

要清楚。它正在做你想做的事:

三个单词字符,后跟 PRI 或 SEC,以及 这不是 SIGSEC

没有人说你必须把所有东西都强加到一个正则表达式中。

【讨论】:

我同意,这可能是最明智的做法。然而,看起来他正在尝试使用正则表达式从文本中提取这些内容 - 不必担心处理您不想要的匹配项可能会导致更简洁的解决方案。

以上是关于仅当字符串的一部分前面没有某些字符时,如何匹配它?的主要内容,如果未能解决你的问题,请参考以下文章

正则表达式匹配捕获组前面没有某些字符

仅当字符串包含指定的内容但没有其他内容时,正则表达式匹配

如何只选择前瞻匹配

仅当两者之间存在某些文本时,正则表达式才匹配星号

仅当内容具有某些单词时,正则表达式才删除括号和内部内容

如何选择将未来的字符串与正则表达式匹配?