有没有办法根据出现的次数替换子字符串?

时间:2015-11-19 18:18:21

标签: java regex

我想删除"*"的所有内容,但忽略"**",例如,如果我有"testing *single star* and **double star**",则删除后的句子将为"testing single star and **double star**"

我正在考虑使用replace("*", "")但是当我尝试使用它时,它已经摆脱了所有的星星。

我该怎么办?

2 个答案:

答案 0 :(得分:7)

您可以利用外观

String s = "testing *single star* and **double star**".replaceAll("(?<![*])[*](?![*])", "");

请参阅IDEONE demo(结果:testing single star and **double star**

*放入字符类可以匹配文字星号而不会转义。

如果星号前没有星号,(?<![*])是负面的后视检查,而(?![*])是一个负向前瞻,确保在匹配星号后没有星号。

答案 1 :(得分:3)

您可以尝试使用

yourString  = yourString.replaceAll("(\\*{2})|\\*","$1");

说明:replaceAll使用正则表达式(regex)机制。此外*是正则表达式中的特殊字符,因此我们需要将其转义(我使用\\*来执行此操作,但您也可以使用[*]或用\\Q {{将其包围起来1}})。现在让我们看看这个正则表达式是什么:

  • \\E - 将尝试匹配(\\*{2})并将其放入第1组
  • ** - OR运算符
  • | - 仅匹配一个\\*

因此,此解决方案将尝试首先找到*,将其存储在第1组中,然后将其替换为第1组中的匹配(因此我们将其替换为自身,这意味着它们将保留在文本中)。 /> 但是,如果正则表达式引擎无法找到**而将找到**,则组1将为空,因为它只能匹配两颗星(因为正则表达式的那部分用括号括起来)。因此,我们的替换*将代表空字符串,这意味着我们将删除单个$1

因此,当前的解决方案将导致这些变化:

*

如果您不想影响2个或更多明星(例如* -> - found 1 star (remove it) ** -> ** - found 2 stars (stay) *** -> ** - found 2 stars (stay), 1 star (remove) **** -> **** - found 2 stars (stay), 2 stars (stay) ***** -> **** - found 2 stars (stay), 2 stars (stay) and 1 star (remove) 仍然应该***)而不是***使用{2},这将允许我们存储在第1组两个或更多星(但不是一个)中。