从字符串连接到格式化参数的自动转换

时间:2015-07-27 17:24:17

标签: java regex

我们的代码中充斥着诸如

之类的东西
Log.d("Hello there " + x + ", I see your are " + y + " years old!");

我希望能够将转换脚本编写为类似的内容,

Log.d("Hello there %s, I see your are %d years old!", x, y);

(注意:我现在并不担心获得正确的参数类型。我可以预先处理文件以确定类型,或者转换为始终使用字符串。现在不是我的担心。)

我想知道是否有人解决了这个问题。我提出了这些正则表达式来拉出字符串的静态和可变部分,

static final Pattern P1 = Pattern.compile("\\s*(\".*?\")\\s*");
static final Pattern P2 = Pattern.compile("\\s*\\+?\\s*([^\\+]+)\\s*\\+?\\s*");

通过循环find(),我可以拉出各个部分,

  • “Hello there”
  • “,我看到你的是”
  • “岁!”

  • X
  • ý

但考虑到如何将它们连接在一起的所有可能性,我无法想出一个很好的方法将它们重新组合在一起。

也许这是错误的方法,我应该尝试拔出,然后用format参数替换变量部分?

有什么想法吗?感谢。

2 个答案:

答案 0 :(得分:1)

如果要将所有内容替换为%s,则可以执行以下操作: (ps:假设用空格表示格式良好的代码)

保持从RIGHT到LEFT的分辨,因为参数位置很重要。

1。)运行此正则表达式以解析表格Log.d({something} + var)Log.d({something}, var)

的所有内容
(Log\.d\(.*?)\"\s*\+\s*([^\s]+)(\+)?(\))

替换

$1%s", $2$4

https://regex101.com/r/hY2iK6/8

2。)现在,您需要注意字符串之间发生的每个变量:

继续运行此正则表达式,直到没有替换出现:

(Log\.d\(.*)(\"\s*\+\s*([^\s]+)\s*\+\s*\")(.*?\"),([^\"]+);

替换

$1%s$4,$3,$5;

运行1之后:https://regex101.com/r/hY2iK6/10

运行2之后:https://regex101.com/r/hY2iK6/11

3.)最后,你需要解决包含一个主要变量的字符串 - 这没问题:

(Log\.d\()([^\"]+)\s+\+\s*\"(.*?),([^"]+;)

替换

$1"%s$3,$2,$4

https://regex101.com/r/hY2iK6/9

可能有的情况,但它应该给你一个想法。

我已将Log.d添加到匹配组及其替换部分,因此如果您愿意,也可以使用Log\.(?:d|f|e)

答案 1 :(得分:0)

您可以使用以下正则表达式一次性捕获所有参数和字符串。因此,您可以使用配对确定参数在整个字符串中的确切位置。

(?:(\w+)\s*\+\s*)?"((?:[^"\\]|\\.)*+)"(?:\s*\+\s*(\w+))?
Regex demo here。 (感谢nhahtdh改进版本。)

它将以格式找到所有连接作为Log.d的一部分:
[<variable> +] <string> [+ <variable>]
其中[]表示可选部分。

使用它可以形成适当的替换,请采用以下示例:

import java.util.regex.Pattern;
import java.util.regex.Matcher;
import java.lang.StringBuilder;
import java.util.List;
import java.util.ArrayList;

class Main {
  public static void main(String[] args) {
    String log = "Log.d(\"Hello there \" + x + \", I see your are \" + y + \" years old!\");";
    System.out.println("Input: " + log);
    Pattern p = Pattern.compile("(?:(\\w+)\\s*\\+\\s*)?\"((?:[^\"\\\\]|\\\\.)*+)\"(?:\\s*\\+\\s*(\\w+))?");
    Matcher m = p.matcher(log);
    StringBuilder output = new StringBuilder(25);
    List<String> arguments = new ArrayList<String>(5);
    output.append("Log.d(\"");
    while (m.find()) {
        if (m.group(1) != null) {
            output.append("%s");
            arguments.add(m.group(1));
        }
        output.append(m.group(2));
        if (m.group(3) != null) {
            output.append("%s");
            arguments.add(m.group(3));
        }
    }
    output.append("\"");
    for (String arg : arguments) {
        output.append(", ").append(arg);
    }
    output.append(");");
    System.out.println("Output: " + output);
  }
}
  

输入:Log.d(&#34;你好那里&#34; + x +&#34;,我看到你的是&#34; + y +&#34;岁了!&#34;) ;
  输出:Log.d(&#34;你好%s,我看你的年龄已经%s了!&#34;,x,y);

Java demo here