我可以替换 Java 正则表达式中的组吗?
我有这段代码,我想知道是否可以仅替换 Java 正则表达式中的组(而不是所有模式)。 代码:
//...
Pattern p = Pattern.compile("(\\d).*(\\d)");
String input = "6 example input 4";
Matcher m = p.matcher(input);
if (m.find()) {
//Now I want replace group one ( (\\d) ) with number
//and group two (too (\\d) ) with 1, but I don't know how.
}
I have this code, and I want to know, if I can replace only groups (not all pattern) in Java regex.
Code:
//...
Pattern p = Pattern.compile("(\\d).*(\\d)");
String input = "6 example input 4";
Matcher m = p.matcher(input);
if (m.find()) {
//Now I want replace group one ( (\\d) ) with number
//and group two (too (\\d) ) with 1, but I don't know how.
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
使用
$n
(其中 n 是数字)来引用replaceFirst(...)
。 我假设您想用文字字符串 "number" 替换第一组,用第一组的值替换第二组。考虑使用(\d) 没有任何内容可匹配时,它必须回溯,然后才能匹配到最终的数字。
(\D+)
作为第二组,而不是(.*)
。*
是一个贪婪匹配器,首先会消耗最后一个数字。 当匹配器意识到最终的编辑
多年后,这个问题仍然得到投票,评论和编辑(打破了答案)表明,人们对这个问题的含义仍然存在困惑。 我已经修复了它,并添加了急需的示例输出。
对替换的编辑(有些人认为不应该使用
$2
)实际上打破了答案。 尽管持续的投票表明答案击中了关键点 - 在replaceFirst(...)
中使用$n
引用来重用捕获的值 - 编辑丢失了未修改文本的事实也需要被捕获,并在替换中使用,以便“仅组(不是所有模式)”。这个问题以及这个答案与迭代无关。 这是故意的 MRE。
Use
$n
(where n is a digit) to refer to captured subsequences inreplaceFirst(...)
. I'm assuming you wanted to replace the first group with the literal string "number" and the second group with the value of the first group.Consider
(\D+)
for the second group instead of(.*)
.*
is a greedy matcher, and will at first consume the last digit. The matcher will then have to backtrack when it realizes the final(\d)
has nothing to match, before it can match to the final digit.Edit
Years later, this still gets votes, and the comments and edits (which broke the answer) show there is still confusion on what the question meant. I've fixed it, and added the much needed example output.
The edits to the replacement (some thought
$2
should not be used) actually broke the answer. Though the continued votes shows the answer hits the key point - Use$n
references withinreplaceFirst(...)
to reuse captured values - the edits lost the fact that unmodified text needs to be captured as well, and used in the replacement so that "only groups (not all pattern)".The question, and thus this answer, is not concerned with iterating. This is intentionally an MRE.
您可以使用
Matcher#start(组)
和Matcher#end(group)
构建通用替换方法:查看在线演示。
You could use
Matcher#start(group)
andMatcher#end(group)
to build a generic replacement method:Check online demo here.
抱歉,死马当活马医,但没有人指出这一点有点奇怪 - “是的,你可以,但这与现实生活中使用捕获组的方式相反”。
如果您按照预期的方式使用正则表达式,解决方案就像这样简单:
或者正如下面 shmosel 正确指出的那样,
...因为在您的正则表达式中根本没有充分的理由对小数进行分组。
您通常不会在要丢弃的字符串部分上使用捕获组,而是在想要保留<的字符串部分上使用它们/em>.
如果您确实想要替换组,那么您可能需要的是模板引擎(例如 moustache、ejs、StringTemplate,...)。
顺便说一句,即使正则表达式中的非捕获组也只是在正则表达式引擎需要它们识别和跳过变量文本的情况下存在。 例如,
如果您的输入看起来像“abcabc捕获我bcdbcd”或“abc捕获我bcd”,甚至只是“捕获我”,则您需要它们。
或者换句话说:如果文本始终相同,并且您没有捕获它,则根本没有理由使用组。
Sorry to beat a dead horse, but it is kind-of weird that no-one pointed this out - "Yes you can, but this is the opposite of how you use capturing groups in real life".
If you use Regex the way it is meant to be used, the solution is as simple as this:
Or as rightfully pointed out by shmosel below,
...since in your regex there is no good reason to group the decimals at all.
You don't usually use capturing groups on the parts of the string you want to discard, you use them on the part of the string you want to keep.
If you really want groups that you want to replace, what you probably want instead is a templating engine (e.g. moustache, ejs, StringTemplate, ...).
As an aside for the curious, even non-capturing groups in regexes are just there for the case that the regex engine needs them to recognize and skip variable text. For example, in
you need them if your input can look either like "abcabccapture mebcdbcd" or "abccapture mebcd" or even just "capture me".
Or to put it the other way around: if the text is always the same, and you don't capture it, there is no reason to use groups at all.
替换输入中的密码字段:
replace the password fields from the input:
您可以使用 matcher.start() 和 matcher.end() 方法来获取组位置。 因此,使用此位置您可以轻松替换任何文本。
You can use matcher.start() and matcher.end() methods to get the group positions. So using this positions you can easily replace any text.
这是一个不同的解决方案,它也允许在多场比赛中替换单个组。
它使用堆栈来反转执行顺序,因此可以安全地执行字符串操作。
Here is a different solution, that also allows the replacement of a single group in multiple matches.
It uses stacks to reverse the execution order, so the string operation can be safely executed.
从 Java 9 开始,您可以使用
Matcher.replaceAll
。用法如下:
output
应等于number example input 6
matchResult.group(0)
是整个模式,因此组是从1
索引Since Java 9 you can use
Matcher.replaceAll
.The usage is as follows:
output
should be equal tonumber example input 6
matchResult.group(0)
is the whole pattern, so groups are indexed from1