仅当字符串的一部分前面没有某些字符时,如何匹配它?
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没有人说你必须把所有东西都强加到一个正则表达式中。
【讨论】:
我同意,这可能是最明智的做法。然而,看起来他正在尝试使用正则表达式从文本中提取这些内容 - 不必担心处理您不想要的匹配项可能会导致更简洁的解决方案。以上是关于仅当字符串的一部分前面没有某些字符时,如何匹配它?的主要内容,如果未能解决你的问题,请参考以下文章