正则表达式使字符串的最后一部分成为可选的,如果它是可选的,则捕获所有内容

Regex make last part of string optional and capture everything if it is optional

我有以下表达式:

(\/.*)@gram_bot

我要匹配:

/echo@gram_bot
/echo

但是如果字符串中有@gram_bot,我想捕获它之前的所有内容,这已经可以了。但是,如果字符串中没有@gram_bot,那么我想捕获整个字符串,只要它以/开头。我怎样才能做到这一点?

我是这样工作的:

(?:(\/.*)@gram_bot|(\/.*))

不过有没有更好的办法。现在我正在用两个单独的组来做,我更喜欢 1 个组和尽可能少的步骤。

您最终可以使用“调和量词”:

/(?:(?!@gram_bot).)*

(如果您选择 ~ 等其他模式分隔符,则不必转义斜线)

demo

步骤更少,但模式更长,您还可以像这样使用展开的循环:

/[^@\n]*(?:@(?!gram_bot)[^@\n]*)*

demo

它被称为 “unrolled” 因为它是 /(?:[^@\n]|@(?!gram_bot))*

的更高效版本

最后,如果你只想在交替中使用一个组,你可以使用分支重置组:

(?|(/.*)@gram_bot|(/.*))

在分支重置组中,每个捕获组具有相同的索引(组1)。

demo

但最后一种方法效率低得多,因为它需要两个分支并且不以文字字符开头。

(\/[^@]*)(?:@gram_bot)?

这应该做你想做的,使用非捕获组 (?:) 和条件 0 或 1 与 ? 作为组本身。

现在,如果 @gram_bot 没有修复,你需要更具体一点,假设你的机器人总是在第一个 @ 之后,你可以使用:

(\/[^@]*)(?:.*)?

您可以在 regex101 上玩一下,看看它如何与 window

右侧的解释一起使用