正则表达式可能有连字符,然后是有限数量的单词字符

时间:2012-05-23 18:14:06

标签: regex

我需要一个正则表达式来匹配包含字符串OKAY然后是一个可能的连字符,然后是零个或一个单词字符的表达式。在此之后,任何非单词字符被接受,然后是任何东西。对于匹配的表达式,如果后面没有单词字符,则OKAY将更改为OK,例如:如果后面的字母为A,则为OA。如果连字符存在,则将其删除。

OKAY         =>       OK
OKAY-        =>       OK
OKAYA        =>       OA
OKAY-A       =>       OA
OKAYAB       =>       OKAYAB          (no-match)
OKAY-AB      =>       OKAY-AB         (no-match)

例子之后可能会出现例如:.CD而不改变结果

OKAY.CD         =>       OK.CD
OKAY-.CD        =>       OK.CD
OKAYA.CD        =>       OA.CD
OKAY-A.CD       =>       OA.CD
OKAYAB.CD       =>       OKAYAB.CD          (no-match)
OKAY-AB.CD      =>       OKAY-AB.CD         (no-match)

我实现这个的问题是,因为连字符和单词字符都是可选的,所以我得到的“懒惰”匹配也匹配非通缉案例。 为了教育,我会很高兴有和没有预见的例子(如果可能的话)。

3 个答案:

答案 0 :(得分:2)

这是一个适合您的正则表达式:

\bOKAY(?>-?)(\w)?([^\w\s]\S*)?(?!\S)

由于您不清楚您使用的是哪种语言,因此这里有伪代码,用于替换。

"O" + (match.group(1) if match.group(1) else "K") + match.group(2)

这是一个rubular:http://www.rubular.com/r/SE8MBkUUUo


编辑:我在评论后对上述正则表达式进行了一些更改,但下面的说明并未反映这些更改。以下是原始正则表达式的更改:

  • ^更改为\b,因此无需从行首开始
  • \W变为[^\w\s],这可以防止OKAY OKAY成为一个匹配
  • .*更改为\S*,以便匹配将以空格结束
  • $更改为(?!\S)(?!\S)表示“只有当我们位于字符串末尾或下一个字符是空格时才匹配”,也可以写为{{1} }}

这里真正棘手的部分是像(?=\s|\z)这样的正则表达式看起来会起作用,但它不适用于像^OKAY-?(\w)?(\W.*)?$这样的情况,因为最后OKAY-AB-?将不匹配,然后(\w)?将匹配字符串的其余部分。

我们需要做的是解决这个问题,因此(\W.*)?不会回溯。如果.NET支持possessive quantifiers,那么这很简单,那么我们可以将其更改为-?

不幸的是,它们不受支持,因此我们需要使用atomic grouping-?+可选地匹配(?>-?),但会在退出组后立即忘记所有回溯信息。请注意,原子组不会捕获,因此-是捕获组1。

答案 1 :(得分:1)

要做到这一点,不要超前,你可以使用

^(OKAY)(((-\w?|\w)(\W.*)?)|[^-\w].*)?$

这匹配单词“OKAY”,然后是一个可选组,其中包含 一个-,一个可选的单词字符,然后是一个可选的非单词字符,后跟任何组, 不是-的字符或后跟任何内容的字符。 ^$分别匹配字符串的开头和结尾,因此它只会匹配可接受的字符串。

Lookaheads几乎没有什么区别。唯一的变化是在“OKAY”组之后对所有内容进行预测((?=...))。

要在.net中使用它,唯一需要的更改是转义字符串中的所有\

答案 2 :(得分:1)

不知道.NET正则表达式,但这是preg-style匹配的开始:

OKAY-?(\w?)([^\w-]\w+)?\s*$

如果$ 1为空,则输出为OK $ 2

否则,输出为O $ 1 $ 2.