在Java'中使用函数或方法;s String.replaceAll()正则表达式

在Java'中使用函数或方法;s String.replaceAll()正则表达式,java,regex,string,Java,Regex,String,我试图将RPN方程转换为符合tigcc规则的字符串。这些数字前面必须有字符数,并带有正负标签。对于“2”,它将是“12 POSINT_标记” 我对rpn converter的完整输入是基于正则表达式的,因此我想再次使用它们,并具有一个String.replaceAll()函数,如: string.replaceAll("(\d+)","$1".length+" $1 POSINT_TAG"); 但它只是打印:“2号INT_标签”。我发现了一些类,比如com.stevesoft.pat() 在普

我试图将RPN方程转换为符合tigcc规则的字符串。这些数字前面必须有字符数,并带有正负标签。对于“2”,它将是“12 POSINT_标记”

我对rpn converter的完整输入是基于正则表达式的,因此我想再次使用它们,并具有一个
String.replaceAll()
函数,如:

string.replaceAll("(\d+)","$1".length+" $1 POSINT_TAG");
但它只是打印:“2号INT_标签”。我发现了一些类,比如com.stevesoft.pat()


在普通Sun Java中是否有其他方法可以在regexes的替换规则中使用(自定义)函数?

没有,至少与在C#或Ruby中使用的方法不同

最接近的方法是编写如下循环:

static Pattern pattern = Pattern.compile("\\d+");
String convert(String input) {
    StringBuffer output = new StringBuffer();
    Matcher matcher = pattern.matcher(input);
    while (matcher.find()) {
        String rep =
            String.format("%d %s POSINT_TAG",
                          matcher.group().length(),
                          matcher.group());
        matcher.appendReplacement(output, rep);
    }
    matcher.appendTail(output);
    return output.toString();
}

不幸的是,你在这里尝试的方法行不通。Java使用应用程序顺序求值,这意味着在调用函数之前对参数求值。在本例中,您得到的是两个字符串的长度
“$1”
,而不是将在组#1中捕获的位数

因此,当您使用这一行时:

string.replaceAll("(\\d+)","$1".length+" $1 POSINT_TAG");   
函数看到的是:

string.replaceAll("(\\d+)","2 $1 POSINT_TAG");  
至于你的问题的解决方案,finnw发布的答案将起作用

我对Java中的自定义字符串替换有一个想法。不像JavaScript中的替换函数那么简单,但它工作得很好。代码如下:


只是为了好玩。

FYI,尽管StringBuilder通常是首选,
appendReplacement()
appendTail()
不接受它;您必须改用StringBuffer。(在JDK 1.4中添加Matcher类时,StringBuilder还不存在。)+1添加到注释中-我一直希望他们会添加这些方法的重载,这些方法可以接受任何可追加的
,但是(在当前的Java 8构建中)仍然只有
StringBuffer
版本。你可能会很高兴知道这一点。这非常有效!我使用了界面而不是反射:

    package org.eve.util;

    import java.lang.reflect.Method;
    import java.lang.reflect.Modifier;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;

    public class StringUtils{
        public static String replaceWithFn(CharSequence input,String regexp,Method fn,int group){
            Matcher m=Pattern.compile(regexp).matcher(input);
            StringBuffer sb=new StringBuffer();
            try {
                Object obj=Modifier.toString(fn.getModifiers()).indexOf("static")>-1?
                        fn.getClass():fn.getDeclaringClass().newInstance();
                if(fn.getReturnType()!=String.class){
                    System.out.println("replacement function must return type \"String\".");
                }
                while(m.find()){
                    m.appendReplacement(sb, (String)fn.invoke(obj, m.group(group)));
                }
                m.appendTail(sb);
            } catch (Exception e) {
                e.printStackTrace();
            }
            return sb.toString();
        }
    }

package org.eve.test;

import org.eve.util.StringUtils;

public class ReplaceTest {
    public static void main(String[] args) {
        try {
            StringBuffer input=new StringBuffer("\\u039D\\u03B9\\u03BA\\u03CC\\u03BB\\u03B1\\u03BF\\u03C2 Nicholas \\u5C3C\\u53E4\\u62C9\\u65AF");
            System.out.println("input="+input);
            String result=StringUtils.replaceWithFn(
                input,
                "\\\\u([0-9a-zA-Z]{4})",
                ReplaceTest.class.getMethod("hex2char",String.class),
                1
            );
            System.out.println("output="+result);
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
    }

    public String hex2char(String s){
        //TODO replaceholder
        return String.valueOf((char)Integer.parseInt(s,16));
    }
}