正则表达式捕获可选令牌后的所有内容

Regex to capture everything after optional token

我的字段包含以下可能格式的数据(每行都有不同的可能性):

AAA - Something Here  
AAA - Something Here - D  
Something Here 

请注意,第一组字母 (AAA) 可以有不同的长度。

我试图捕获的是使用 PCRE 的“Something Here”或“Something Here - D”(如果存在),但我无法让正则表达式在所有三种情况下都正常工作。我试过:

- (.*) 适用于情况 1 和 2,但显然不适用于情况 3;

(?<= - )(.*) 也适用于情况 1 和 2;

(?! - )(.+)| - (.+) 适用于情况 2 和 3 但不适用于情况 1。

我觉得我快要崩溃了,但我似乎无法破解它。

在此先感谢您的帮助。

编辑:我意识到我的要求不清楚。如果后面有一个“-D”(数据中的字母是任意的,但应该只是一个字符),也需要捕获它。

您可以使用

^(?:.*? - )?\K.*?(?= - | *$)
^(?:.*?\h-\h)?\K.*?(?=\h-\h|\h*$)

regex demo

详情

  • ^ - 字符串的开头 -(?:.*? - )? - 一个可选的非捕获组匹配除换行符之外的任何 0+ 个字符,尽可能少到第一个 space-space
  • \K - 匹配重置运算符
  • .*? - 除换行字符外的任何 0+ 个字符尽可能少
  • (?= - | *$) - space-space 或直到字符串末尾的 0+ 个空格应紧跟在右侧。

请注意 \h 匹配任何水平空白字符。

关于您尝试过的模式:

  • - (.*)此模式将匹配第一次出现的 - ,然后匹配该行的其余部分。对于第二个示例,它会匹配太多,因为 .* 也会匹配第二次出现的 -
  • (?<= - )(.*)这个模式将匹配第一个没有 - 的例子,因为它断言应该直接出现在左边
  • (?! - )(.+)| - (.+) 此模式使用否定前瞻,它断言直接在右边的不是 (?! - )。由于示例的none以 - 开头,由于.+的否定先行后会直接匹配整行,而交替后的第二部分|将不会匹配评价

如果第一组字母的长度可以变化,您可以匹配特定匹配的 1 个或多个大写字符 [A-Z]+ 或 1+ 个单词字符 \w+.

要获得更广泛的匹配,您可以使用 \S+

匹配 1 个或多个非空白字符
^(?:\S+\h-\h)?\K\S+(?:\h(?!-\h)\S+)*

说明

  • ^ 字符串开头
  • (?:\S+\h-\h)? 可选择匹配第一组非空白字符,后跟 - 水平空白字符
  • \K清除匹配缓冲区(忘记当前匹配的是什么)
  • \S+匹配1+个非空白字符
  • (?:非捕获组
    • \h(?!-\h) 匹配水平空白字符并断言直接在右边的不是 - 后跟另一个水平空白字符
    • \S+ 匹配 1+ 个非空白字符
  • )*关闭非捕获组并重复1+次以匹配更多由空格分隔的“单词”

Regex demo

编辑

要匹配可选的连字符和尾随的单个字符,您可以添加可选的非捕获组 (?:-\h\S\h*)?$ 并在模式应匹配整个字符串时断言字符串的结尾:

^(?:\S+\h-\h)?\K\S+(?:\h(?!-\h)\S+)*\h*(?:-\h\S\h*)?$
                                       

Regex demo

^(?:[A-Z]+ - \K)?.*\S

demo

因为 "Something Here" 可以是任何东西,所以没有理由专门描述模式中最终的最后一个字母。你不需要更复杂的东西。

对于这种模式,我假设您对尾随空格不感兴趣,这就是我以 \S 结尾的原因。如果要保留它们,请删除 \S 并将之前的量词更改为 +.