我目前正在尝试使用正则表达式解决codingbat.com的问题。
我是新手,所以一步一步的解释将不胜感激。我可以相对容易地使用String方法解决这个问题,但我正在尝试使用正则表达式。
以下是提示: 给定一个字符串和一个非空字符串,在字符串中每次出现单词之前和之后返回由每个char组成的字符串。忽略在单词之前或之后没有字符的情况,如果字符位于两个单词之间,则可以包括两次char。
wordEnds("abcXY123XYijk", "XY") → "c13i"
wordEnds("XY123XY", "XY") → "13"
wordEnds("XY1XY", "XY") → "11"
等
到目前为止我的代码:
String regex = ".?" + word+ ".?";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(str);
String newStr = "";
while(m.find())
newStr += m.group().replace(word, "");
return newStr;
问题在于,当一行中有多个单词实例时,程序会错过单词前面的字符,因为m.find()会超出它。
例如:wordEnds("abc1xyz1i1j", "1")
应返回"cxziij"
,但我的方法返回"cxzij"
,而不是重复"i"
我很感激一个非混乱的解决方案,并且可以解释我可以应用于其他一般的正则表达式问题。
答案 0 :(得分:1)
这是一个单线解决方案:
String wordEnds = input.replaceAll(".*?(.)" + word + "(?:(?=(.)" + word + ")|(.).*?(?=$|." + word + "))", "$1$2$3");
这与您的边缘情况相匹配,作为非捕获组内的前瞻,然后匹配通常(消费)情况。
请注意,您的要求不需要迭代,只有您的问题标题认为是必要的,而不是。
另请注意,为了绝对安全,您应该转义word
中的所有字符,以防其中任何字符是特殊的“正则表达式”字符,因此如果您无法保证,则需要使用{{1而不是Pattern.quote(word)
。
这是对常见案例和边缘案例的测试,显示它有效:
word
输出:
public static String wordEnds(String input, String word) {
word = Pattern.quote(word); // add this line to be 100% safe
return input.replaceAll(".*?(.)" + word + "(?:(?=(.)" + word + ")|(.).*?(?=$|." + word + "))", "$1$2$3");
}
public static void main(String[] args) {
System.out.println(wordEnds("abcXY123XYijk", "XY"));
System.out.println(wordEnds("abc1xyz1i1j", "1"));
}
答案 1 :(得分:0)
使用正向后观和正向前瞻,这是零宽度断言
(?<=(.)|^)1(?=(.)|$)
^ ^ ^-looks for a character after 1 and captures it in group2
| |->matches 1..you can replace it with any word
|
|->looks for a character just before 1 and captures it in group 1..this is zero width assertion that doesn't move forward to match.it is just a test and thus allow us to capture the values
$1
和$2
包含您的价值。继续寻找到最后
所以这应该像
String s1 = "abcXY123XYiXYjk";
String s2 = java.util.regex.Pattern.quote("XY");
String s3 = "";
String r = "(?<=(.)|^)"+s2+"(?=(.)|$)";
Pattern p = Pattern.compile(r);
Matcher m = p.matcher(s1);
while(m.find()) s3 += m.group(1)+m.group(2);
//s3 now contains c13iij
工作here
答案 2 :(得分:0)
使用正则表达式如下:
Matcher m = Pattern.compile("(.|)" + Pattern.quote(b) + "(?=(.?))").matcher(a);
for (int i = 1; m.find(); c += m.group(1) + m.group(2), i++);
检查 this demo 。