2011-01-20 22 views
5

Bir RPN denklemini tigcc kurallarına uyan bir dizgeye dönüştürmeye çalışıyorum. Sayıların önlerinde karakter sayısı ve olumlu veya olumsuz bir etiket olması gerekir. "2" için bu "1 2 POSINT_TAG"Java'nın String.replaceAll() regex işlevlerini veya yöntemlerini kullanma

rpn dönüştürücü Benim komple giriş regexes dayanmaktadır olacağını, bu yüzden onları yeniden kullanmak istedi ve sahip bir String.replaceAll() fonksiyonu gibi:

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

Ama Sadece yazdırır: "2 adet INT_TAG". Com.stevesoft.pat (link) gibi bazı sınıflar buldum.

Normal Sun Java'da, normal ifadeler yerine kullanılan (özel) işlevleri kullanmak için başka bir yol var mı?

cevap

13

Hayır, en azından C# veya Ruby'de yaptığınız gibi değil.

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(); 
} 
+3

FYI, StringBuilder genellikle tercih edilir, 'appendReplacement() 've' appendTail() 'bunu kabul etmez; Bunun yerine StringBuffer kullanmalısınız. (StringBuilder henüz Matcher sınıfı eklendiğinde, JDK 1.4'te bulunmadı.) –

+0

+1 yorumu - Ben herhangi bir 'Appendable' alabilecek bu yöntemlerin aşırı yüklenmesini ekleyeceğini umuyoruz Java 8, hala sadece 'StringBuffer' sürümü var. –

+1

[Bu cevabı Android için Yığın Taşımı mobil uygulamasının kaynak kodunda alıntılanmıştır] (http://meta.stackexchange.com/a/277077/254929) bilmek için eğlendirilebilir. – Air

1

Maalesef burada ne çalışıyorsunuz işe gitmiyor:

yakın şey böyle bir döngü yazmaktır. Java, işlevler çağrılmadan önce argümanların değerlendirildiğini ifade eden uygulama emri değerlendirmesini kullanır. Sizin durumunuzda, # 1 numaralı grupta yakalanacak rakam sayısını değil, "$1" iki karakterli dizginin uzunluğunu elde edersiniz.

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

Ne işlevi görür ise:

Yani bu hattı kullandığınızda soruna bir çözüm olarak

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

, finnw tarafından gönderildi cevap çalışacaktır.

3

Java'da özel dizgi değiştirme hakkında bir fikrim var. JavaScript'te değiştirme işlevi kadar kolay değil, ancak iyi çalışıyor. Sadece eğlence için


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

: İşte kodudur.

+0

Bu mükemmel çalışıyor! Yansıma yerine bir arabirim kullandım: https://github.com/redstone/LegacyFactions/blob/fcf1410e99cbe1e82fabcf84827b44e01af719a6/src/main/java/net/redstoneore/legacyfactions/util/StringUtils.java#L8 –

İlgili konular