【问题标题】:Regular Expression to exclude Word ending with _OK正则表达式排除以 _OK 结尾的单词
【发布时间】:2016-10-17 21:10:11
【问题描述】:

对于以下条目,我想排除以_OK 结尾的词 我找到了一个匹配以_OK 结尾的单词的正则表达式 但我想找到相反的结果

此正则表达式匹配以 _OK 结尾的单词

\b(\w+(?:_OK))\b

输入:

SMHST_BI_V2016AUG
SMHST BI V2016AUG_OK
SMHST_BI_V2016SEP
SMHST_BI_V2016SEP_OK

【问题讨论】:

  • 这在正则表达式中可能会也可能不会,这取决于您使用的库或编程语言(您需要“负前瞻”,这并不总是可用)。但是,您当然可以使用您拥有的正则表达式,然后从控制代码中处理所有 匹配的行。这有意义吗?
  • 另外,SMHST BI V2016AUG_OK 是拼写错误,还是您想将SMHSTBI 视为有效匹配项?

标签: regex


【解决方案1】:

你可以使用:

\b\w+(?<!_OK)\b

Live demo

根据 Wiktor 的建议,您可以使 + 具有所有格以更快。


另外,请注意,大多数时候,这种通用请求可以通过简单的!Contains() 来处理

【讨论】:

  • 通过这种方法,我会使用\b\w++(?&lt;!_OK)\b,所有格量词将使正则表达式引擎在没有回溯选项的情况下抓取单词字符,并且_OK 只会被检查一次 在这些单词字符匹配之后。
  • @WiktorStribiżew 我已经测试过了,它似乎快了两倍!谢谢:)
  • 是的,请注意,某些支持后备的引擎不支持所有格量​​词(例如 Python re)。这就是为什么前瞻版本更能跨引擎兼容的原因。
  • 我不会想到在比赛的结束使用消极的后视!请添加有关哪些正则表达式引擎支持(?&lt;!...)++ 的注释,但是,负面的lookbehind 绝对不是通用的,我以前从未听说过++
【解决方案2】:

有两种方法。

使用负前瞻 (demo):

\b(?!\w*_OK\b)\w+\b

或消极的回顾:

\b\w+\b(?<!_OK)

another demo

第一个选项适用于大多数 NFA 正则表达式引擎(例如 PCRE、JavaScript、Python、.NET、Java、Oniguruma/Onigmo、ICU),而第二个选项只能用于那些支持后向 (.NET) 的引擎, PCRE, Python, Java, ICU, Oniguruma/Onigmo)。请注意,在 RE2 和 Go 中,根本不支持环视。

详情

  • \b - 前导词边界
  • (?!\w*_OK\b) - 如果在当前位置后面有 0+ 个单词字符后跟 _OK 后跟单词边界,则匹配失败
  • \w+ - 1 个或多个单词字符,后跟
  • \b - 词尾边界。

\b\w+\b(?&lt;!_OK) 模式类似,但(?&lt;!_OK) 否定回溯仅在匹配整个单词后触发一次,如果在当前位置之前有一个_OK 字符序列,则匹配失败(即,与\w+匹配的单词后面的单词边界)。

【讨论】:

  • 再一次,你更快了;做得好!你的lookbehind和我的有什么不同还是他们的行为一样?
  • 我发表了一条关于如何使您的模式更快的评论。
【解决方案3】:

从正则表达式中执行此操作所需的“前瞻”和/或“后瞻”功能并不总是可用的。相反,您可以反转外部控制逻辑,仅处理 匹配的行。例如,在 Perl 中你会写

while (<>) {
    chomp;
    next if /_OK$/;
    # if we get here, $_ does _not_ end in "_OK"
}

或者,在 shell 提示符下,

grep -v '_OK$' < file_to_process | further_steps

如您所见,这种技术还可以让您使用更简单的正则表达式。

(Perl 正则表达式确实具有前瞻/后瞻功能;我之所以使用它,是因为它对于“外部控制逻辑”非常方便。)

【讨论】:

    猜你喜欢
    • 2016-05-09
    • 1970-01-01
    • 2022-08-02
    • 2013-08-26
    • 1970-01-01
    • 2018-02-10
    • 1970-01-01
    • 2019-04-30
    相关资源
    最近更新 更多