【问题标题】:Using functions or methods in Java's String.replaceAll() regex在 Java 的 String.replaceAll() 正则表达式中使用函数或方法
【发布时间】:2011-01-20 00:06:04
【问题描述】:

我正在尝试将 RPN 方程转换为与 tigcc 规则匹配的字符串。数字前面必须有字符数和正负标记。对于“2”,它将是“1 2 POSINT_TAG”

我对 rpn 转换器的完整输入是基于正则表达式的,所以我想再次使用它们并拥有一个 String.replaceAll() 函数,例如:

string.replaceAll("(\d+)","$1".length+" $1 POSINT_TAG");

但它只打印:“2 number INT_TAG”。我发现了一些像 com.stevesoft.pat (link) 这样的类。

在普通的 Sun Java 中是否有另一种方法可以在正则表达式的替换规则中使用(自定义)函数?

【问题讨论】:

    标签: java regex string


    【解决方案1】:

    不,至少不像在 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();
    }
    

    【讨论】:

    • 仅供参考,虽然 StringBuilder 通常是首选,appendReplacement()appendTail() 不接受它;您必须改用 StringBuffer 。 (在 JDK 1.4 中添加 Matcher 类时,StringBuilder 还不存在。)
    • +1 评论 - 我一直希望他们会添加这些方法的重载,这些方法可以采用任何 Appendable,但是(截至当前的 Java 8 版本)仍然只有 StringBuffer版本。
    【解决方案2】:

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

    
        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));
        }
    }
    

    纯娱乐。

    【讨论】:

    【解决方案3】:

    不幸的是,您在这里尝试的方法行不通。 Java 使用应用顺序评估,这意味着在调用函数之前对参数进行评估。在您的情况下,您得到的是两个字符串 "$1" 的长度,而不是第 1 组中将捕获的位数。

    所以当你使用这条线时:

    string.replaceAll("(\\d+)","$1".length+" $1 POSINT_TAG");   
    

    函数看到的是:

    string.replaceAll("(\\d+)","2 $1 POSINT_TAG");  
    

    至于您的问题的解决方案,finnw 发布的答案将起作用。

    【讨论】:

      猜你喜欢
      • 2013-05-27
      • 1970-01-01
      • 2011-04-25
      • 2023-03-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多