Java 从字符串连接到格式化参数的自动转换
我们的代码到处都是这样的东西Java 从字符串连接到格式化参数的自动转换,java,regex,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); (注意:我现在不担心获得正确的参数类型。我可以预处理文件以确定类型,或者转换为始终使用字符串。我现在不担心。) 我想知道是否有人已经解决了这个问题。我想出了这些正则表达
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()
,我可以拉出每个零件
- “你好”
- “我知道你是”
- “岁!”
- x
- y
有什么想法吗?谢谢。如果要将所有内容替换为
%s
,可以执行以下操作:
(注:假设代码格式良好,以空格表示)
保持从右到左的分辨率,因为参数位置很重要
1.)运行这个正则表达式来解析形式为Log.d({something}+var)
到Log.d({something},var)
替换
$1%s", $2$4
$1%s$4,$3,$5;
$1"%s$3,$2,$4
()
2.)现在,您需要注意字符串之间出现的每个变量:
继续运行此正则表达式,直到没有替换项出现:
(Log\.d\(.*)(\"\s*\+\s*([^\s]+)\s*\+\s*\")(.*?\"),([^\"]+);
替换
$1%s", $2$4
$1%s$4,$3,$5;
$1"%s$3,$2,$4
运行1后:
运行2后:
3.)最后,您需要解析包含前导变量的字符串-这没有问题:
(Log\.d\()([^\"]+)\s+\+\s*\"(.*?),([^"]+;)
替换
$1%s", $2$4
$1%s$4,$3,$5;
$1"%s$3,$2,$4
可能有一些案例没有涵盖,但它应该会给你一个想法
我将
Log.d
添加到匹配组及其替换部分,因此您可以使用Log\(?:d | f | e)
如果您愿意,您可以使用以下正则表达式一次性捕获所有参数和字符串。因此,您可以使用这些对来准确地找出参数在整个字符串中的位置
(?:(\w+)\s*\+\s*)?“((?:[^“\\]\124;\\)*+)”(?:\ s*\+\s*(\w+))”
(感谢提供改进版的。) 它将以以下格式查找作为Log.d一部分的所有连接:
[+][+]
其中,
[]
表示可选零件
这样,您就可以形成适当的替换,以下面的示例为例:
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);
}
}
import java.util.regex.Pattern;
导入java.util.regex.Matcher;
导入java.lang.StringBuilder;
导入java.util.List;
导入java.util.ArrayList;
班长{
公共静态void main(字符串[]args){
String log=“log.d(\'Hello there\'+x+\”,我看到你的年龄是\“+y+\”岁!\”;
System.out.println(“输入:“+log”);
模式p=Pattern.compile((?:(\\w+\\s*\\+\\s*)?\”((?:[^\“\\\\].*+)\(?:\\s*\\\\+\\s*(\\w+)))\”;
匹配器m=p.Matcher(对数);
StringBuilder输出=新StringBuilder(25);
列表参数=新的ArrayList(5);
output.append(“Log.d(\”);
while(m.find()){
如果(m.group(1)!=null){
输出。追加(“%s”);
添加(m.group(1));
}
输出追加(m.group(2));
如果(m.group(3)!=null){
输出。追加(“%s”);
添加(m.组(3));
}
}
output.append(“\”);
for(字符串参数:参数){
output.append(“,”).append(arg);
}
输出。追加(“);”;
System.out.println(“输出:”+输出);
}
}
输入:Log.d(“你好”+x+,我看到你是”+y+“岁!”)输出:Log.d(“您好,这里是%s,我看到您已经%s岁了!”,x,y)
.即使有正则表达式来翻译它,只要看一下
x
和y
,你就无法(不检查逻辑)确定是否应该使用%s
,%d
-或其他任何东西。你如何知道如何使用%s
或%d
或%f
?是,格式类型不是我现在担心的部分。我可以预处理文件并确定变量的类型。现在更多的是在正确的位置用限定符构造格式化字符串。嗯,也许是个愚蠢的想法。是否有机会将所有这些Log.d
调用grep到一个文件中,并对它们进行排列,使它们能够编译并在您之前将变量设置为%s
的上下文中执行,然后运行它,并以某种方式替换原始结果。如果存在转义的\”
s,例如Log.d(“值是\“+x+”\)
(?充其量只是一个补丁,因为它不知道在“
之前有多少个
。对于字符串文字,应该使用正则表达式”(?:[^“\]\124;\)*+“
@nhahdh在这种情况下,前面有多少个”并不重要。”
。在引号之前只有奇数个反斜杠才是java中的有效字符串。但是如果您想彻底,我想您的方式最好。@nhahdh True,我稍后会调整我的解决方案。谢谢。基于您的重新编写的正则表达式:(不需要惰性量词-实际上所有量词都可以设为所有格,但我只设字符串字面所有格)感谢深思熟虑的回答。不幸的是,有两个。