正则表达式获取模式的最后一个匹配项

时间:2020-10-27 15:53:12

标签: regex regex-lookarounds regex-group

这里是一个与我要匹配的字符串相似的字符串(为简单起见,有几个特定的​​模式除外)。 Hello, tonight I'm in the town of Trenton in New Jersey and I will be staying in Hotel HomeStay [123] and I have no money.

我正在尝试仅匹配最后一个in Hotel HomeStay [123]

我对正则表达式概念(例如前瞻和后瞻)不是很熟悉。类似的问题在这里似乎无法解决我的问题。我已经尝试了一堆正则表达式(据我所知),这就是我想到的(?= (?:in|\d+))([\w \[]*\s*\d*\]*)(?!.*in)。数字和特殊字符可能是我实际尝试匹配的部分。

先行和后退模式不限于仅包含in。它们也可以具有更常见的单词,例如andis。我只是在寻找所有这些的最后一次出现,然后是主要模式,该模式非常有特色- edit 让我们说匹配项必须包含HomeStay或{{ 1}},为方便起见。

但是,这与整个LuxuryInn相匹配。 我要去哪里错了?另外,有人可以解释为什么in the town of Trenton in New Jersey and I will be staying in Hotel HomeStay [123]尽管被置于非捕获组中却被捕获了吗?

非常感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

在Java中:

String s = "Hello, tonight I'm in the town of Trenton in New Jersey and I will be "
           + "staying in Hotel HomeStay [123] and I have no money.";
// Garbage: final String SUBP = "\\bin\\s+(\\S+)";
Pattern p = Pattern.compile("^.*\\sin\\s+(\\S+).*$", Pattern.DOTALL);
String last = p.matcher(s).replaceFirst("$1"); // If found

这将找到最后个“ ...在...中”,因为.*(而不是急切的.*?)将寻找最长的序列。

上面的结果将是Hotel({{1}之后没有空格),但可以是任何东西。


  • 全部使用将使in也匹配换行符。
  • 模式将从开始.到结束^
  • 任何字符$(最长),后跟空白字符.*
  • 然后“输入”,然后在第1组\s中输入一个单词(非空格\S+
  • 然后将所有字符保留到(...)的末尾。出于纯度考虑,它应该是最短序列的.*
  • 结局.*?

答案 1 :(得分:1)

如果要检索包含HomeStay且带有某些单词前缀但不包含这些单词的文本,则可以使用内部使用负向预视的捕获组。下面的正则表达式捕获所有出现的事件(working fiddle)。

\b(?:in|and|is)\s+((?:.(?!\b(?:in|and|is)\b))*HomeStay(?:.(?!\b(?:in|and|is)\b))*)

在这里,正则表达式查找:

  • 给定前缀(inandis作为整个词,并由分词器 \b
  • ...之后至少要有一个空白字符
  • ...然后是一个0或多个字符的序列每个字符后没有前缀
  • ...后跟HomeStay
  • ...后跟另一个0或多个字符的序列,每个序列仍不跟前缀

如果只希望最后一次出现,则可以在(fiddle)之后添加另一个否定的前瞻。

\b(?:in|and|is)\s+((?:.(?!\b(?:in|and|is)\b))*HomeStay(?:.(?!\b(?:in|and|is)\b))*)(?!.*HomeStay.*)

与上述相同,除了匹配的文本后不能包含HomeStay

最后,如果匹配的文本必须至少包含一个列表中的单词,只需用替代列表替换出现的HomeStay。寄宿家庭和豪华房示例:(?:HomeStay|Luxury)fiddle)。