Reputation: 93
I am trying to convert an RPN-equation into a string that matches tigcc rules. There numbers must have the number of chars in front of them and a tag for positive or negative. For "2" it would be "1 2 POSINT_TAG"
My complete input to rpn converter is based on regexes, so I wanted to use them again and have a String.replaceAll()
function like:
string.replaceAll("(\d+)","$1".length+" $1 POSINT_TAG");
But there it just prints: "2 number INT_TAG". I found some classes like com.stevesoft.pat (link).
Is there another way implemented in normal Sun Java to use (custom) functions in replace rules of regexes?
Upvotes: 6
Views: 4946
Reputation: 953
Unfortunately what you are attempting here isn't going to work. Java uses applicative order evaluation meaning that the arguments are evaluated before the function is ever called. In your case you are getting the length of the two-character string "$1"
, not the number of digits that will be captured in group #1.
So when you use this line:
string.replaceAll("(\\d+)","$1".length+" $1 POSINT_TAG");
What the function sees is:
string.replaceAll("(\\d+)","2 $1 POSINT_TAG");
As for a solution to your problem, the answer posted by finnw will work.
Upvotes: 1
Reputation: 31
I have a idea about custom string replacement in Java. Not as easy as replacement function in JavaScript but it just works fine. Here is the code:
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));
}
}
Just for fun.
Upvotes: 3
Reputation: 48619
No, at least not the same way you would do it in C# or Ruby.
The closest thing is to write a loop like this:
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();
}
Upvotes: 13