正则表达式替换特定子字符串前后的特定字符

8
我正在进行Java CodingBat练习。 这里 是我刚完成的一个练习:

给定一个字符串和一个非空单词字符串,返回由每个单词出现前后的字符组成的字符串。忽略没有单词前后字符的情况,并且如果一个字符在两个单词之间,则可以包含两次。

下面是我的代码,它可以正常工作:
public String wordEnds(String str, String word){

    String s = "";
    String n = " " + str + " "; //To avoid OOB exceptions

    int sL = str.length();
    int wL = word.length();
    int nL = n.length();

    int i = 1;

    while (i < nL - 1) {

        if (n.substring(i, i + wL).equals(word)) {
            s += n.charAt(i - 1);
            s += n.charAt(i + wL);
            i += wL;
        } else {
            i++;
        }
    }

    s = s.replaceAll("\\s", "");

    return s;
}

我的问题与正则表达式有关。我想知道是否可以使用正则表达式语句来实现上述操作,如果可以,那么如何实现呢?

这个问题可能很难用Java正则表达式来解决,因为匹配可能会重叠,例如abcXY1XYijk在匹配XY时将具有cXY11XYi作为组。 - Tim Biegeleisen
顺便说一句,好问题 ^ ^ - Tim Biegeleisen
иѕ“е…Ґпјљint a = 5, b = 3; int sum = a + b;иѕ“е‡єпјљsumзљ„еЂјдёє8гЂ‚ - vks
1
UTF-16 是一种变宽度的编码方式,每个字符占据一个或两个代码单元。因此 chatAt 是错误的。 - tchrist
3个回答

3
您可以使用Java正则表达式对象 Pattern Matcher 来完成此操作。
public class CharBeforeAndAfterSubstring {
    public static String wordEnds(String str, String word) {
        java.util.regex.Pattern p = java.util.regex.Pattern.compile(word);
        java.util.regex.Matcher m = p.matcher(str);
        StringBuilder beforeAfter = new StringBuilder();

        for (int startIndex = 0; m.find(startIndex); startIndex = m.start() + 1) {
            if (m.start() - 1 > -1)
                beforeAfter.append(Character.toChars(str.codePointAt(m.start() - 1)));
            if (m.end() < str.length())
                beforeAfter.append(Character.toChars(str.codePointAt(m.end())));
        }

        return beforeAfter.toString();
    } 
    public static void main(String[] args) {
        String x = "abcXY1XYijk";
        String y = "XY";
        System.out.println(wordEnds(x, y));

    }
} 

我很欣赏问题中的“可能”部分是含糊不清的。在这种情况下,它应该被包括进来,否则测试就会失败。 - alanbuchanan
@alanbuchanan 编辑了答案,请查看。添加了一些索引逻辑,以确保重叠部分被正确计算。 - Narendra Yadala
这在Unicode的16/17个平面上无法正常工作。请停止使用charAt:它不适合此用途。 - tchrist
感谢@tchrist。已经修正。这是一个初学者的问题,所以并没有太在意Unicode。 - Narendra Yadala

1
为了获取一个包含另一个字符串中每个出现前后字符的字符串,您可以使用正则表达式表达式:
"(^|.)" + str + "(.|$)"

然后您可以遍历这些组并将它们连接起来。
此表达式将查找(^|.),即字符串的开头^或任何字符.,后跟str值,后跟(.|$),任何字符.或字符串的结尾$
您可以尝试类似于以下内容:
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public String wordEnds(String str, String word){
    Pattern p = Pattern.compile("(.)" + str + "(.)");
    Matcher m = p.matcher(word);
    String result = "";
    int i = 0;
    while(m.find()) {
        result += m.group(i++);
    }
    return result;
}

它如何执行“返回一个字符串,该字符串由字符串中每个出现单词之前和之后的字符组成”? - Scary Wombat
感谢 @Scary Wombat 的反馈。你是对的。我替换了那些字符,而不是返回它们,这与要求相反。已更新答案。 - Moishe Lipsker
你的代码在 http://codingbat.com/prob/p147538 上的大部分测试都失败了,而这正是原始问题(OP)试图从中学习的地方。 - user883499
@user883499 在表达式中更新了逻辑。 - Moishe Lipsker

1

这并没有考虑到XY可能是其他东西,就像问题中由str定义的那样。 - alanbuchanan

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接