Java正则表达式最短匹配

问题描述 投票:1回答:4

我有以下字符串,(a.1) (b.2) (c.3) (d.4)。我想把它改成(1) (2) (3) (4)。我使用以下方法。

str.replaceAll("\(.*[.](.*)\)","($1)")。我只得到(4)。什么是正确的方法?

谢谢

java regex
4个回答
2
投票

在这里结合一些事首先,您对括号的转义不正确。在Java字符串文字中,反斜杠本身是一个转义字符,这意味着您需要使用\\(来表示正则表达式中的\(

我认为你的问题是如何在正则表达式中进行非贪婪的匹配。使用?指定非贪婪匹配;例如*?的意思是“零次或多次,但尽可能少”。

这并不能否定其他答案,但它们取决于您的测试输入是否与您的问题一样简单。这给了我正确的输出而不改变原始正则表达式的精神(只知道括号和点分隔符存在):

String test = "(a.1) (b.2) (c.3) (d.4)";
String replaced = test.replaceAll("\\(.*?[.](.*?)\\)", "($1)");
System.out.println(replaced); // "(1) (2) (3) (4)"

2
投票

尝试这个,它将匹配任何字母,."并用空""替换它们

str.replaceAll("[a-zA-Z\\.\"]", "") 

编辑:

你也可以使用[^\\d)(\\s]来匹配所有不是数字,空格和)(的字符,并用空的""字符串替换它们

String str  = "(a.1) (b.2) (c.3) (d.4)";
System.out.println(str.replaceAll("[^\\d)(\\s]",""));

2
投票

根本原因

你想匹配()分隔的子串,但使用的.*贪婪点模式可以匹配任何0或更多的字符(除了换行符)。 \(.*[.](.*)\)模式将匹配(中的第一个(a.1) (b.2) (c.3) (d.4),然后.*将获取整个字符串,并且回溯将开始尝试为随后的强制性子模式容纳文本。 [.]将在字符串中找到最后一个.,最后一个数字前面的那个4。然后,(.*)将再次抓住所有其余的弦,但由于后来需要),由于回溯最后的(.*)将只捕获4

为什么懒惰/不情愿的.*?不是解决方案?

即使你使用\(.*?[.](.*?)\),如果在字符串中有(xxx)之类的子串,它们将与预期的匹配匹配,因为.匹配任何char但是换行符。

.replaceAll("\\([^()]*\\.([^()]*)\\)", "($1)")

regex demo[^()]只会匹配任何字符,但()

细节

  • qazxsw poi - 一张qazxsw poi图表
  • \( - 一个否定的字符类,匹配除([^()]*之外的0个或更多个字符
  • ( - 一个点
  • ) - 第1组(其值后来用替换模式中的\.引用):除了([^()]*)$1之外的任何0+字符
  • qazxsw poi - 一张qazxsw poi图表。

(

)

输出:

\)

0
投票

试试这个

)

Java demo将匹配大写,小写和数字。如果你想在点(。)之前匹配任何东西,你可以使用List<String> strs = Arrays.asList("(a.1) (b.2) (c.3) (d.4)", "(a.1) (xxxx) (b.2) (c.3) (d.4)"); for (String str : strs) System.out.println("\"" + str.replaceAll("\\([^()]*\\.([^()]*)\\)", "($1)") + "\""); "(1) (2) (3) (4)" "(1) (xxxx) (2) (3) (4)" 代替str.replaceAll("[A-Za-z0-9]+\.","");

© www.soinside.com 2019 - 2024. All rights reserved.