英文:
replace Java-regex-quantifiers
问题
我有一个类似于 "18+,a + b" 的字符串。我可以在 Java 11 中用 "\+" 替换所有符号 "+" 吗?
我尝试使用 replaceAll("\+", "\+"),但出现了 "Dangling meta character '+'" 的错误。
请帮助我,谢谢。
英文:
I have a string like "18+, a + b". Can I replace all symbol "+" by "\+" in Java 11.
I try replaceAll("+", "\+") but failed by Dangling meta character '+'
Exception in
thread "main" java.util.regex.PatternSyntaxException: Dangling meta character '+' near index 0
+
^
at java.base/java.util.regex.Pattern.error(Pattern.java:2045)
at java.base/java.util.regex.Pattern.sequence(Pattern.java:2220)
at java.base/java.util.regex.Pattern.expr(Pattern.java:2086)
at java.base/java.util.regex.Pattern.compile(Pattern.java:1798)
at java.base/java.util.regex.Pattern.<init>(Pattern.java:1445)
at java.base/java.util.regex.Pattern.compile(Pattern.java:1084)
at java.base/java.lang.String.replaceAll(String.java:2950)
Please help me, thank you
答案1
得分: 1
TL;DR: 你需要使用 .replace
,而不是 .replaceAll
。它将替换所有出现的内容(是的,.replace
会替换所有,就像 replaceAll
一样),并且不会抱怨悬挂的元字符。
这里是解释:
a.replace("needle", "duck")
将所有的 "needle" 替换为 "duck"。a.replaceAll("needleRegex", "duck")
解析第一个字符串参数作为正则表达式(这是一种编程语言概念,用于描述正则文法,而+
在此语言中具有特殊意义,这就是为什么会出现错误)。然后用 "duck" 替换a
中与正则表达式匹配的所有子字符串。.replaceAll
是正则表达式版本,而.replace
是普通字符串版本。a.replaceFirst("needleRegex", "duck")
类似于replaceAll
,但在替换第一个找到的子字符串后停止。
换句话说,All/First
相互对比,这些方法命名非常不合适,或者根本不应该成为 Java<sup>1</sup> 的一部分。如果这些方法真的需要存在,要么 [A] 应该将 Pattern
作为第一个参数(Java 强烈支持名义类型,如果有一个表示事物的类型,应该使用它),要么 [B] 应该命名为 .regexReplaceAll
。
因此,我强烈建议大家永远不要使用 .replaceAll
。如果你真的想使用正则表达式(它可以非常强大,但你应该需要它,而不是让一些代码意外地应用正则表达式解析),那么创建一个模式,使用其替换所有方法。这样,你的代码更加灵活(例如:如果解析正则表达式是性能紧密循环的一部分,你可以将其隔离出来。你可以显式设置参数,并使用模式/匹配器公开的各种方法,而不仅仅是 replaceAll/replaceFirst/matches)- 当别人阅读代码时,不会感到困惑:你正在使用正则表达式,这是显而易见的,而且显然你是有意的。
<sup>1</sup> Java 通常比较重视向后兼容性;因此,我怀疑这些方法不会被移除,甚至不会被标记为过时/不推荐使用/不明智,因为那会破坏现有的代码。然而,生态系统可能(应该!)采取行动;代码审查工具应该默认提供建议,不要使用这些方法,集成开发环境应该在自动完成对话框中删除或至少在视觉上不鼓励使用这些方法,等等。
英文:
TL;DR: You want .replace
. Not .replaceAll
. Which will replace all occurrences (Yes, .replace
replaces all, as does replaceAll
) - and won't complain about dangling metacharacters.
Here's how it breaks down:
a.replace("needle", "duck")
turns all needles into ducks.a.replaceAll("needleRegex", "duck")
parses the first string argument as a regular expression (which is a programming language-esque concept to describe regular grammars, and+
has significance in this language, hence why you got your error). Then replaces all substrings withina
that match the regex with"duck"
..replaceAll
is the regular expression version,.replace
is the plain strings version.a.replaceFirst("needleRegex", "duck")
is likereplaceAll
, except it stops after replacing the first substring it finds.
In other words, All/First
contrast to each other, and these methods are very badly named / should never have been part of java<sup>1</sup>. The appropriate methods, if they are to exist at all, either [A] should have taken a Pattern
as first argument (java is strongly nominally typed, if there's a type that represents the thing, use it), or [B] should have been named .regexReplaceAll
instead.
As a consequence I strongly advise all to never use .replaceAll
. If you really want to futz with regular expressions (can be quite powerful, but you should want them, you don't want some code to arbitrarily apply regex parsing as a surprise), make a pattern, use its replace-all methods instead. That way, your code is more flexible (Example: If parsing the regex is part of a profiler's performance tight loop, you can isolate it. You can explicitly set parameters, and use the vast array of methods pattern/matcher expose, instead of just replaceAll/replaceFirst/matches) - and nobody will be confused when reading it: You are using regexes, it is obvious that you are, and it is obvious that you intended to.
<sup>1</sup> Java tends to take backwards compatibility fairly seriously; as a consequence I doubt these methods will be removed or even marked as obsolete/deprecated/ill-advised, because that would break existing code. However, the ecosystem may (should!) make a move; linter tools should ship out of the box advising against it, IDEs should remove or at least visually disencourage these methods in their auto-complete dialogs, and so on.
答案2
得分: 1
是的,您可以使用String#replace方法。String#replaceAll方法在这里不是必需的,它是对replace的替代方法,允许输入正则表达式模式。
String string = "18+, a + b";
string = string.replace("+", "\\+");
输出
18\+, a \+ b
英文:
> "... Can I replace all symbol "+" by "+" in Java 11. ..."
Yes, you can use the String#replace method.
The String#replaceAll method isn't required here, it is an alternative to replace which allows for a regular expression pattern as input.
String string = "18+, a + b";
string = string.replace("+", "\\+");
Output
18\+, a \+ b
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论