Java中的正则表达式问题

Java中的正则表达式问题,java,regex,Java,Regex,我试图在Java中为replaceAll方法创建一个正则表达式。测试字符串是abXYabcXYZ,模式是abc。我想用+替换除图案之外的任何符号。例如,字符串abXYabcXYZ和模式[^(abc)]应该返回+++++abc++,但在我的例子中,它返回ab+++abc++ public static String plusOut(String str, String pattern) { pattern= "[^("+pattern+")]" + "".toLowerCase();

我试图在Java中为
replaceAll
方法创建一个正则表达式。测试字符串是
abXYabcXYZ
,模式是
abc
。我想用
+
替换除图案之外的任何符号。例如,字符串
abXYabcXYZ
和模式
[^(abc)]
应该返回
+++++abc++
,但在我的例子中,它返回
ab+++abc++

public static String plusOut(String str, String pattern) {
    pattern= "[^("+pattern+")]" + "".toLowerCase();
    return str.toLowerCase().replaceAll(pattern, "+");
}
public static void main(String[] args) {
    String text = "abXYabcXYZ";
    String pattern = "abc";
    System.out.println(plusOut(text, pattern));
}
当我尝试用
+
替换模式时,没有问题-
abXYabcXYZ
用模式
(abc)
返回
abxy+xyz
。模式
(^(abc))
返回不替换的字符串


是否有其他方法将NOT(正则表达式)或分组符号作为一个单词写入?

[^…]将匹配一个不属于以下任何字符的字符

因此,您的模式“[^(abc)]”表示“匹配一个不是a、b、c或左括号或右括号的字符”;事实上,这就是你测试中发生的事情

在一个简单的正则表达式中很难说“替换所有不属于字符串“abc”的字符”。你可能会做些什么来实现你想要的可能是一些令人讨厌的事情,比如

while the input string still contains "abc"
   find the next occurrence of "abc"
   append to the output a string containing as many "+"s as there are characters before the "abc"
   append "abc" to the output string
   skip, in the input string, to a position just after the "abc" found
append to the output a string containing as many "+"s as there are characters left in the input
replace all occurrences of "abc" with a single character that does not occur anywhere in the existing string
replace all other characters with "+"
replace all occurrences of the target character with "abc"
或者,如果输入字母表受到限制,您可以使用正则表达式执行以下操作

while the input string still contains "abc"
   find the next occurrence of "abc"
   append to the output a string containing as many "+"s as there are characters before the "abc"
   append "abc" to the output string
   skip, in the input string, to a position just after the "abc" found
append to the output a string containing as many "+"s as there are characters left in the input
replace all occurrences of "abc" with a single character that does not occur anywhere in the existing string
replace all other characters with "+"
replace all occurrences of the target character with "abc"

它的可读性更高,但执行起来可能不太好

对regexp进行否定通常是很麻烦的。我想你可能想使用负前瞻。类似的方法可能会奏效:

String pattern = "(?<!ab).(?!abc)";

String pattern=“(?正则表达式很难实现,因为无法表示“替换不匹配模式的字符串”。您必须使用“正”模式,告诉匹配的内容而不是不匹配的内容

此外,您希望用替换字符替换每个字符,因此您必须确保模式恰好匹配一个字符。否则,您将用单个字符替换整个字符串,并返回一个较短的字符串

对于您的玩具示例,您可以使用否定的查找表和LoopBeNeDS来完成任务,但是对于具有更长或更复杂字符串的真实世界示例来说,这可能更加困难,因为您必须单独考虑字符串的每个字符以及上下文。

以下是“非abc”的模式:

[^abc]|a(?!bc)|(?<!a)b|b(?!c)|(?<!ab)c
[^abc]| a(?!bc)|(?
它由五个子模式组成,与“或”(
|
)相连,每个子模式正好匹配一个字符:

  • [^abc]
    匹配除
    a
    b
    c
  • a(?!bc)
    匹配
    a
    ,如果它后面没有
    bc
  • (?匹配
    b
    ,如果前面没有
    a
  • b(?!c)
    匹配
    b
    如果后面没有
    c
  • (?匹配
    c
    ,如果前面没有
    ab
这样做的目的是匹配每个不在目标单词abc中的字符,再加上每个根据上下文不在单词中的字符。可以使用否定lookaheads
(?!…)
和lookbehinds
(?)检查上下文

您可以想象,如果目标词不止一次包含一个字符,该技术就会失败,如
示例
。如果后面没有
x
l
,则很难表示“匹配
e


特别是对于动态模式,更容易进行正向搜索,然后在第二遍中替换所有不匹配的字符,正如其他人在此建议的那样。

尝试在不使用正则表达式的情况下解决此问题:

String out = "";
int i;
for(i=0; i<text.length() - pattern.length() + 1; ) {
    if (text.substring(i, i + pattern.length()).equals(pattern)) {
        out += pattern;
        i += pattern.length();
    }
    else {
        out += "+";
        i++;
    }
}
for(; i<text.length(); i++) {
    out += "+";
}
String out=”“;
int i;

对于(i=0;i而不是一个replaceAll,您可以尝试以下方法:

   @Test
    public void testString() {
        final String in = "abXYabcXYabcHIH";
        final String expected = "xxxxabcxxabcxxx";
        String result = replaceUnwanted(in);
        assertEquals(expected, result);
    }

    private String replaceUnwanted(final String in) {
        final Pattern p = Pattern.compile("(.*?)(abc)([^a]*)");
        final Matcher m = p.matcher(in);
        final StringBuilder out = new StringBuilder();
        while (m.find()) {
            out.append(m.group(1).replaceAll(".", "x"));
            out.append(m.group(2));
            out.append(m.group(3).replaceAll(".", "x"));
        }
        return out.toString();
    }

我不使用
replaceAll(…)
,而是选择
模式/匹配器
方法:

import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class Main {

    public static String plusOut(String str, String pattern) {
        StringBuilder builder = new StringBuilder();
        String regex = String.format("((?:(?!%s).)++)|%s", pattern, pattern);
        Matcher m = Pattern.compile(regex).matcher(str.toLowerCase());
        while(m.find()) {
            builder.append(m.group(1) == null ? pattern : m.group().replaceAll(".", "+"));
        }
        return builder.toString();
    }

    public static void main(String[] args) {
        String text = "abXYabcXYZ";
        String pattern = "abc";
        System.out.println(plusOut(text, pattern));
    }

}
请注意,如果
字符串模式
包含正则表达式元字符,则需要使用
模式.quote(…)


编辑:我没有看到一个
模式/匹配器
方法已经被推荐了(虽然略有不同)

是的,这就是我要做的。但是尝试用正则表达式来做这件事是一个很好的难题。