我正在尝试解决wordEnds来自codingbat.com使用正则表达式。
给定一个字符串和一个非空单词字符串,返回由字符串中该单词每次出现之前和之后的每个字符组成的字符串。忽略单词前后没有字符的情况,如果字符位于两个单词之间,则可能会包含两次。
wordEnds("abcXY123XYijk", "XY") → "c13i"
wordEnds("XY123XY", "XY") → "13"
wordEnds("XY1XY", "XY") → "11"
wordEnds("XYXY", "XY") → "XY"
这是最简单的,因为我可以用我目前的正则表达式知识来做到这一点:
public String wordEnds(String str, String word) {
return str.replaceAll(
".*?(?=word)(?<=(.|^))word(?=(.|$))|.+"
.replace("word", java.util.regex.Pattern.quote(word)),
"$1$2"
);
}
replace
用于放置在实际中word
字符串到模式中以提高可读性。Pattern.quote
不需要通过他们的测试,但我认为这是基于正则表达式的正确解决方案所必需的。
正则表达式有两个主要部分:
- If after matching as few characters as possible "
.*?
", word
can still be found "(?=word)
", then lookbehind to capture any character immediately preceding it "(?<=(.|^))
", match "word
", and lookforward to capture any character following it "(?=(.|$))
".
- 最初的“if”测试确保原子后向捕获仅当存在
word
- 使用前瞻捕获后续字符不会消耗它,因此它可以用作进一步匹配的一部分
- Otherwise match what's left "
|.+
"
我认为这在所有情况下都有效,但显然相当复杂。我只是想知道其他人是否可以建议一个更简单的正则表达式来做到这一点。
注意:我不是在寻找使用的解决方案indexOf
和一个循环。我想要一个基于正则表达式的replaceAll
解决方案。我还需要一个可以通过所有codingbat 测试的有效正则表达式。
我设法减少了这种情况的发生word
模式内只有一个。
".+?(?<=(^|.)word)(?=(.?))|.+"
我仍在寻找是否可以进一步简化这一点,但我还有另一个问题:
- 通过这个最新的模式,我简化了
.|$
只是.?
成功了,但如果我同样尝试简化^|.
to .?
它不起作用。这是为什么?