我有以下字符串,(a.1) (b.2) (c.3) (d.4)
。我想把它改成(1) (2) (3) (4)
。我使用以下方法。
str.replaceAll("\(.*[.](.*)\)","($1)")
。我只得到(4)
。什么是正确的方法?
谢谢
在这里结合一些事首先,您对括号的转义不正确。在Java字符串文字中,反斜杠本身是一个转义字符,这意味着您需要使用\\(
来表示正则表达式中的\(
。
我认为你的问题是如何在正则表达式中进行非贪婪的匹配。使用?
指定非贪婪匹配;例如*?
的意思是“零次或多次,但尽可能少”。
这并不能否定其他答案,但它们取决于您的测试输入是否与您的问题一样简单。这给了我正确的输出而不改变原始正则表达式的精神(只知道括号和点分隔符存在):
String test = "(a.1) (b.2) (c.3) (d.4)";
String replaced = test.replaceAll("\\(.*?[.](.*?)\\)", "($1)");
System.out.println(replaced); // "(1) (2) (3) (4)"
尝试这个,它将匹配任何字母,.
和"
并用空""
替换它们
str.replaceAll("[a-zA-Z\\.\"]", "")
编辑:
你也可以使用[^\\d)(\\s]
来匹配所有不是数字,空格和)(
的字符,并用空的""
字符串替换它们
String str = "(a.1) (b.2) (c.3) (d.4)";
System.out.println(str.replaceAll("[^\\d)(\\s]",""));
根本原因
你想匹配()
分隔的子串,但使用的.*
贪婪点模式可以匹配任何0或更多的字符(除了换行符)。 \(.*[.](.*)\)
模式将匹配(
中的第一个(a.1) (b.2) (c.3) (d.4)
,然后.*
将获取整个字符串,并且回溯将开始尝试为随后的强制性子模式容纳文本。 [.]
将在字符串中找到最后一个.
,最后一个数字前面的那个4
。然后,(.*)
将再次抓住所有其余的弦,但由于后来需要)
,由于回溯最后的(.*)
将只捕获4
。
为什么懒惰/不情愿的.*?
不是解决方案?
即使你使用\(.*?[.](.*?)\)
,如果在字符串中有(xxx)
之类的子串,它们将与预期的匹配匹配,因为.
匹配任何char但是换行符。
解
.replaceAll("\\([^()]*\\.([^()]*)\\)", "($1)")
见regex demo。 [^()]
只会匹配任何字符,但(
和)
。
细节
\(
- 一个否定的字符类,匹配除(
和[^()]*
之外的0个或更多个字符(
- 一个点)
- 第1组(其值后来用替换模式中的\.
引用):除了([^()]*)
和$1
之外的任何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]+\.","");