首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Java regex:将除给定字符串实例之外的所有字符替换为`+`

Java regex:将除给定字符串实例之外的所有字符替换为`+`
EN

Stack Overflow用户
提问于 2018-09-13 12:59:35
回答 7查看 6.9K关注 0票数 24

我有以下问题,它说明

将字符串中的所有字符替换为+符号,但方法中给定字符串的实例除外

例如,如果给定的字符串是abc123efg,而他们希望我替换除123实例之外的所有字符,那么它将变为+++123+++

我认为正则表达式可能是最好的,所以我想出了这个。

代码语言:javascript
复制
str.replaceAll("[^str]","+") 

其中str是一个变量,但它不允许我在不加引号的情况下使用该方法。如果我只想替换变量字符串,我该怎么做呢?我用手动输入的字符串运行它,它在方法上起作用,但我能只输入一个变量吗?

到目前为止,我相信它正在寻找字符串"str“,而不是变量字符串。

下面是输出结果,除了两种情况外,它在很多情况下都是正确的:(

打开的测试用例列表:

代码语言:javascript
复制
plusOut("12xy34", "xy") → "++xy++"
plusOut("12xy34", "1") → "1+++++"
plusOut("12xy34xyabcxy", "xy") → "++xy++xy+++xy"
plusOut("abXYabcXYZ", "ab") → "ab++ab++++"
plusOut("abXYabcXYZ", "abc") → "++++abc+++"
plusOut("abXYabcXYZ", "XY") → "++XY+++XY+"
plusOut("abXYxyzXYZ", "XYZ") → "+++++++XYZ"
plusOut("--++ab", "++") → "++++++"
plusOut("aaxxxxbb", "xx") → "++xxxx++"
plusOut("123123", "3") → "++3++3"
EN

回答 7

Stack Overflow用户

发布于 2018-09-13 14:21:19

看起来这就是CodingBat上的plusOut问题。

对于这个问题,我有3个解决方案,我写了一个新的流媒体解决方案,只是为了好玩。

解决方案1:循环和检查

根据输入字符串创建一个StringBuilder,并检查每个位置的单词。如果不匹配,则替换该字符,如果找到,则跳过该单词的长度。

代码语言:javascript
复制
public String plusOut(String str, String word) {
  StringBuilder out = new StringBuilder(str);

  for (int i = 0; i < out.length(); ) {
    if (!str.startsWith(word, i))
      out.setCharAt(i++, '+');
    else
      i += word.length();
  }

  return out.toString();
}

这可能是初学者的预期答案,尽管有一个假设字符串不包含任何星形平面字符,这将由2个字符而不是1来表示。

解决方案2:用标记替换单词,替换其余单词,然后恢复单词

代码语言:javascript
复制
public String plusOut(String str, String word) {
    return str.replaceAll(java.util.regex.Pattern.quote(word), "@").replaceAll("[^@]", "+").replaceAll("@", word);
}

这不是一个正确的解决方案,因为它假设某个字符或字符序列不出现在字符串中。

注意,使用Pattern.quote来防止replaceAll方法将word解释为正则表达式语法。

解决方案3:使用\G的正则表达式

代码语言:javascript
复制
public String plusOut(String str, String word) {
  word = java.util.regex.Pattern.quote(word);
  return str.replaceAll("\\G((?:" + word + ")*+).", "$1+");
}

构造正则表达式\G((?:word)*+).,它或多或少地完成了solution 1正在做的事情:

  • \G确保匹配从前一个匹配留下的位置开始,off
  • ((?:word)*+)挑选出0个或更多个word实例-如果有的话,这样我们就可以用$1替换它们。这里的关键是所有格量词*+,它强制正则表达式保留它找到的word的任何实例。否则,当字符串末尾出现word时,正则表达式将无法正常工作,因为匹配.
  • .的正则表达式回溯将不会是任何word的一部分,因为前一部分已经挑选出word的所有连续外观并禁止回溯。我们将用+

替换它

解决方案4:流媒体

代码语言:javascript
复制
public String plusOut(String str, String word) {
  return String.join(word, 
    Arrays.stream(str.split(java.util.regex.Pattern.quote(word), -1))
      .map((String s) -> s.replaceAll("(?s:.)", "+"))
      .collect(Collectors.toList()));
}

其思想是通过word拆分字符串,对其余部分进行替换,然后使用String.join方法将它们与word连接起来。

  • 和上面一样,我们需要Pattern.quote来避免splitword解释为正则表达式。由于split在默认情况下会删除数组末尾的空字符串,因此我们需要在第二个参数中使用-1来使split保留这些空字符串。
  • 然后我们在数组之外创建一个流,并将其余的替换为+的字符串。在Java11中,我们可以使用s -> String.repeat(s.length())
  • 剩下的只是将流转换为一个迭代(在本例中为List),并将它们连接起来以得到
票数 16
EN

Stack Overflow用户

发布于 2018-09-13 13:26:49

这可能比您最初认为的要复杂一些,因为您不仅需要匹配字符,而且缺少特定的短语-一个被否定的字符集是不够的。如果字符串是123,则需要:

代码语言:javascript
复制
(?<=^|123)(?!123).*?(?=123|$)

https://regex101.com/r/EZWMqM/1/

也就是说,对于字符串的开头或"123",请确保当前位置后面没有123,然后延迟重复任何字符,直到lookahead匹配"123“或字符串的结尾。这将匹配不在"123“子字符串中的所有字符。然后,您需要将每个字符替换为+,然后您可以使用appendReplacementStringBuffer创建结果字符串:

代码语言:javascript
复制
String inputPhrase = "123";
String inputStr = "abc123efg123123hij";
StringBuffer resultString = new StringBuffer();
Pattern regex = Pattern.compile("(?<=^|" + inputPhrase + ")(?!" + inputPhrase + ").*?(?=" + inputPhrase + "|$)");
Matcher m = regex.matcher(inputStr);
while (m.find()) {
    String replacement = m.group(0).replaceAll(".", "+");
    m.appendReplacement(resultString, replacement);
}
m.appendTail(resultString);
System.out.println(resultString.toString());

输出:

代码语言:javascript
复制
+++123+++123123+++

请注意,如果inputPhrase可以在正则表达式中包含具有特殊含义的字符,则在连接到模式之前必须首先对它们进行转义。

票数 6
EN

Stack Overflow用户

发布于 2018-09-13 14:21:11

你可以用一行代码来完成:

代码语言:javascript
复制
input = input.replaceAll("((?:" + str + ")+)?(?!" + str + ").((?:" + str + ")+)?", "$1+$2");

这将选择性地捕获每个字符的两侧的"123“,并将它们放回原处(如果没有”123“,则为空):

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/52306904

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档