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

发布于 2024-07-07 13:08:54 字数 390 浏览 10 评论 0原文

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

(\w{3}PRI$|[^SIG].*SEC$)

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

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

谢谢, 富有的

I've created the following regex pattern in an attempt to match a string 6 characters in length ending in either "PRI" or "SEC", unless the string = "SIGSEC". For example, I want to match ABCPRI, XYZPRI, ABCSEC and XYZSEC, but not SIGSEC.

(\w{3}PRI$|[^SIG].*SEC$)

It is very close and sort of works (if I pass in "SINSEC", it returns a partial match on "NSEC"), but I don't have a good feeling about it in its current form. Also, I may have a need to add more exclusions besides "SIG" later and realize that this probably won't scale too well. Any ideas?

BTW, I'm using System.Text.RegularExpressions.Regex.Match() in C#

Thanks,
Rich

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

蓝海似她心 2024-07-14 13:08:54

假设您的正则表达式引擎支持负向先行,请尝试以下操作:

((?!SIGSEC)\w{3}(?:SEC|PRI))

编辑:评论者指出 .NET 确实支持负向先行,因此这应该可以正常工作(谢谢,查理)。

Assuming your regex engine supports negative lookaheads, try this:

((?!SIGSEC)\w{3}(?:SEC|PRI))

Edit: A commenter pointed out that .NET does support negative lookaheads, so this should work fine (thanks, Charlie).

踏雪无痕 2024-07-14 13:08:54

为了帮助分解 Dan 的(正确)答案,它是这样工作的:

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

一起: ((?!SIGSEC)\w{3}(?:SEC|PRI))

To help break down Dan's (correct) answer, here's how it works:

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

All together: ((?!SIGSEC)\w{3}(?:SEC|PRI))

梦回梦里 2024-07-14 13:08:54

您可以尝试这个:

@"\w{3}(?:PRI|(?<!SIG)SEC)"
  • 匹配 3 个“单词”字符
  • 匹配 PRI 或 SEC(但不在 SIG 之后,即排除 SIGSEC) (? < !x)y - 是负向后查找(如果前面没有 x,则计算 y)

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

使用我的代码,您可以轻松添加另一个例外,例如以下代码排除 SIGSEC 和 FOOSEC

@"\w{3}(?:PRI|(?<!SIG|FOO)SEC)"

You can try this one:

@"\w{3}(?:PRI|(?<!SIG)SEC)"
  • Matches 3 "word" characters
  • Matches PRI or SEC (but not after SIG i.e. SIGSEC is excluded) (? < !x)y - is a negative lookbehind (it mathces y if it's not preceded by x)

Also, I may have a need to add more
exclusions besides "SIG" later and
realize that this probably won't scale
too well

Using my code, you can easily add another exceptions, for example following code excludes SIGSEC and FOOSEC

@"\w{3}(?:PRI|(?<!SIG|FOO)SEC)"
屌丝范 2024-07-14 13:08:54

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

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);
}

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

Why not use more readable code? In my opinion this is much more maintainable.

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;
}

or in one line

private Boolean HasValidEnding(String input)
{
    return (input.EndsWith("SEC",StringComparison.Ordinal) || input.EndsWith("PRI",StringComparison.Ordinal)) && !input.Equals("SIGSEC",StringComparison.Ordinal);
}

It's not that I don't use regular expressions, but in this case I wouldn't use them.

寂寞清仓 2024-07-14 13:08:54

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

exclude = 'someexpression'; 之类的东西 prefix = '前缀列表'; suffix = '后缀列表'; 表达式 = '{前缀}{排除}{后缀}';

Personally, I'd be inclined to build-up the exclusion list using a second variable, then include it into the full expression - it's the approach I've used in the past when having to build any complex expression.

Something like exclude = 'someexpression'; prefix = 'list of prefixes'; suffix = 'list of suffixes'; expression = '{prefix}{exclude}{suffix}';

苦笑流年记忆 2024-07-14 13:08:54

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

if ( ( $str =~ /^\w{3}(?:PRI|SEC)$/ ) && ( $str ne 'SIGSEC' ) )

以保持清晰。 它完全按照您的要求进行操作:

  • 三个单词字符,后跟 PRI 或 SEC,并且
  • 不是 SIGSEC

没有人说您必须将所有内容强制放入一个正则表达式中。

You may not even want to do the exclusions in the regex. For example, if this were Perl (I don't know C#, but you can probably follow along), I'd do it like this

if ( ( $str =~ /^\w{3}(?:PRI|SEC)$/ ) && ( $str ne 'SIGSEC' ) )

to be clear. It's doing exactly what you wanted:

  • Three word characters, followed by PRI or SEC, and
  • It's not SIGSEC

Nobody says you have to force everything into one regex.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文