为了账号安全,请及时绑定邮箱和手机立即绑定

我如何用正则表达式替换这个函数

我如何用正则表达式替换这个函数

炎炎设计 2023-04-26 14:28:37
我有一个格式为 yy_MM_someRandomString_originalFileName 的文件名。例子:02_01_fEa3129E_my Pic.png我想将前 2 个下划线替换为,/以便示例变为:02/01/fEa3129E_my Pic.png这可以用 replaceAll 来完成,但问题是文件也可能包含下划线。@Testvoid test() {    final var input = "02_01_fEa3129E_my Pic.png";    final var formatted = replaceNMatches(input, "_", "/", 2);    assertEquals("02/01/fEa3129E_my Pic.png", formatted);}private String replaceNMatches(String input, String regex,                               String replacement, int numberOfTimes) {    for (int i = 0; i < numberOfTimes; i++) {        input = input.replaceFirst(regex, replacement);    }    return input;}我使用循环解决了这个问题,但是有没有纯正则表达式的方法来做到这一点?编辑:这种方式应该能够让我更改参数并将下划线的数量从 2 增加到 n。
查看完整描述

2 回答

?
慕娘9325324

TA贡献1783条经验 获得超4个赞

您可以使用 2 个捕获组并在替换中使用它们,其中匹配项_将被替换为/

^([^_]+)_([^_]+)_

用。。。来代替:

$1/$2/

正则表达式演示Java演示

例如:

String regex = "^([^_]+)_([^_]+)_";

String string = "02_01_fEa3129E_my Pic.png";

String subst = "$1/$2/";


Pattern pattern = Pattern.compile(regex);

Matcher matcher = pattern.matcher(string);

String result = matcher.replaceFirst(subst);


System.out.println(result);

结果


02/01/fEa3129E_my Pic.png


查看完整回答
反对 回复 2023-04-26
?
阿晨1998

TA贡献2037条经验 获得超6个赞

您当前的解决方案几乎没有问题:


这是低效的——因为每个都replaceFirst需要从字符串的开头开始,所以它需要多次迭代相同的起始字符。


它有一个错误- 因为第 1 点。当从开始而不是最后修改的地方迭代时,我们可以替换之前插入的值。


例如,如果我们想两次替换单个字符,每次都用Xlike abc->XXc在代码 like 之后


String input = "abc";

input = input.replaceFirst(".", "X"); // replaces a with X -> Xbc

input = input.replaceFirst(".", "X"); // replaces X with X -> Xbc

Xbc我们将以instead of结尾XXc,因为第二个replaceFirst将替换为Xwith Xinstead of bwith X。


为避免此类问题,您可以重写代码以使用Matcher#appendReplacement和Matcher#appendTail方法,以确保我们将迭代输入一次并可以用我们想要的值替换每个匹配的部分


private static String replaceNMatches(String input, String regex,

                               String replacement, int numberOfTimes) {


    Matcher m = Pattern.compile(regex).matcher(input);

    StringBuilder sb = new StringBuilder();

    int i = 0;

    while(i++ < numberOfTimes && m.find() ){

        m.appendReplacement(sb, replacement); // replaces currently matched part with replacement, 

                                              // and writes replaced version to StringBuilder 

                                              // along with text before the match

    }

    m.appendTail(sb); //lets add to builder text after last match

    return sb.toString();

}

使用示例:


System.out.println(replaceNMatches("abcdefgh", "[efgh]", "X", 2)); //abcdXXgh


查看完整回答
反对 回复 2023-04-26
  • 2 回答
  • 0 关注
  • 187 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信