这里是一个与我要匹配的字符串相似的字符串(为简单起见,有几个特定的模式除外)。
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
。它们也可以具有更常见的单词,例如and
和is
。我只是在寻找所有这些的最后一次出现,然后是主要模式,该模式非常有特色- edit 让我们说匹配项必须包含HomeStay
或{{ 1}},为方便起见。
但是,这与整个LuxuryInn
相匹配。
我要去哪里错了?另外,有人可以解释为什么in the town of Trenton in New Jersey and I will be staying in Hotel HomeStay [123]
尽管被置于非捕获组中却被捕获了吗?
非常感谢您的帮助。
答案 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
也匹配换行符。.
到结束^
。$
(最长),后跟空白字符.*
。\s
中输入一个单词(非空格\S+
)(...)
的末尾。出于纯度考虑,它应该是最短序列的.*
。.*?
。答案 1 :(得分:1)
如果要检索包含HomeStay
且带有某些单词前缀但不包含这些单词的文本,则可以使用内部使用负向预视的捕获组。下面的正则表达式捕获所有出现的事件(working fiddle)。
\b(?:in|and|is)\s+((?:.(?!\b(?:in|and|is)\b))*HomeStay(?:.(?!\b(?:in|and|is)\b))*)
在这里,正则表达式查找:
in
,and
或is
作为整个词,并由分词器 \b
)HomeStay
,如果只希望最后一次出现,则可以在(fiddle)之后添加另一个否定的前瞻。
\b(?:in|and|is)\s+((?:.(?!\b(?:in|and|is)\b))*HomeStay(?:.(?!\b(?:in|and|is)\b))*)(?!.*HomeStay.*)
与上述相同,除了匹配的文本后不能包含HomeStay
。
最后,如果匹配的文本必须至少包含一个列表中的单词,只需用替代列表替换出现的HomeStay
。寄宿家庭和豪华房示例:(?:HomeStay|Luxury)
(fiddle)。