Hi I'm trying to setup a hostname pattern for a minecraft-server plugin. It will look through the arguments of the chat message and try to find any possible hostnames. The code works unless the message only contains one word.
Here's the class that checks the message event:
package com.carlgo11.preventip.player;
import com.carlgo11.preventip.Main;
import java.util.regex.Matcher;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.player.AsyncPlayerChatEvent;
public class ChatEvent implements Listener {
Main plugin;
public ChatEvent(Main plug)
{
super();
this.plugin = plug;
}
#EventHandler
public void PlayerChat(AsyncPlayerChatEvent e)
{
if (!plugin.getConfig().getBoolean("ignore-chat")) {
Player p = e.getPlayer();
String msg = e.getMessage();
String[] args = msg.split(" ");
Boolean match = false;
if (!p.hasPermission("preventip.ignore")) {
for (int i = 0; i < args.length; i++) {
Matcher hnre = plugin.hostnamePattern.matcher(msg.toString());
Boolean hnrematch = hnre.find();
if (hnrematch) {
match = true;
break;
}
}
if (match) {
e.setCancelled(true);
Action.action(p, plugin);
}
}
}
}
}
And here's the pattern
Pattern hostnamePattern = Pattern.compile("^(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])$");
So when args contains more than 1 word the pattern works but if not the pattern acts as true even though hnre.find() outputs false.
Thanks in advance :)
First at all, please use Java Naming Conventions (see https://stackoverflow.com/tags/java/info).
About your method design there is something that I find a little strange, first you split the message:
String[] args = msg.split(" ");
but then you try to match your regex with the whole message, for each word in your message:
Matcher hnre = plugin.hostnamePattern.matcher(msg.toString());
I think you can simplify all doing something like:
//remove ^ and $ to find the pattern in any position in your message. I assume the correctness of the pattern
Pattern hostnamePattern = Pattern.compile("(([a-zA-Z0-9]|[a-zA-Z0-9][a-zA-Z0-9\\-]*[a-zA-Z0-9])\\.)*([A-Za-z0-9]|[A-Za-z0-9][A-Za-z0-9\\-]*[A-Za-z0-9])");
//Let msg a annoying message
String msg = "ereh un enfermo, ereh un enfermo, ereh un enfermo de ciberseso me pone loh cuenno " +
"me pone lo cuenno www.tiahbuena.com esto vida mia eh un infienno";
Matcher m = hostnamePattern.matcher(msg);
boolean hnrematch = m.find();
if(hnrematch){
//cancel what you want
}
Hope it helps
Related
I'm trying to use the PhoneNumberMatcher from the libphonenumber library. After adding the jar file to my project and setting the BuildPath, I was able to import classes to my project:
import com.google.i18n.phonenumbers.*;
Inside the lib, there is a class named PhoneNumberMatcher.class. I've been trying to reach it but this class name isn't included in suggestions I normally get when I press Ctrl + Space.
If I insist and write the name class, eclipse will underline the name and the message "The type PhoneNumberMatcher is not visible".
Newly I realized that the class has a small blue flag icon is in the project explorer.
It's not the only one that has such a blue flag, then I try the other classes and I realized that all classes with this blue flag isn't accessible. That's why I think these classes probably are private, or for internal use of the lib.
I'm trying to create a tool to extract phone numbers out of a text and I read this lib is exactly for it.
How do I use the PhonNumberMatcher class in my java project, please?
CharSequence text = "Call me at +1 425 882-8080 for details.";
String country = "US";
PhoneNumberUtil util = PhoneNumberUtil.getInstance();
// Find the first phone number match:
PhoneNumberMatch m = util.findNumbers(text, country).iterator().next();
// rawString() contains the phone number as it appears in the text.
"+1 425 882-8080".equals(m.rawString());
// start() and end() define the range of the matched subsequence.
CharSequence subsequence = text.subSequence(m.start(), m.end());
"+1 425 882-8080".contentEquals(subsequence);
// number() returns the the same result as PhoneNumberUtil.parse()
// invoked on rawString().
util.parse(m.rawString(), country).equals(m.number());
https://javadoc.io/doc/com.googlecode.libphonenumber/libphonenumber
Thank you for your answer Chana.
I did actually was able to use the library, but then I realized that the lib was to complicated to use for me, so I did write my own code to extract German phone numbers, IBANs, Postcodes and money amounts and then classify then:
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class NumberExtractorAndClassifier {
public static final String REGEXPhoneNumbers = "(0|0049\\s?|\\+49\\s?|\\(\\+49\\)\\s?|\\(0\\)\\s?){1}([0-9]{2,4})([ \\-\\/]?[0-9]{1,10})+";
public static final String REGEXIbanNumbers = "([A-Z][ -]?){2}([0-9]([ -]?)*){12,30}";
public static final String REGEXAmounts = "(\\d+([.,]?)\\d{0,}([.,]?)\\d*(\\s*)(\\$|€|EUR|USD|Euro|Dollar))|((\\$|€|EUR|USD|Euro|Dollar)(\\s*)\\d+([.,]?\\d{0,}([.,]?)\\d*))";
public static final String REGEXPostCode = "\\b((?:0[1-46-9]\\d{3})|(?:[1-357-9]\\d{4})|(?:[4][0-24-9]\\d{3})|(?:[6][013-9]\\d{3}))\\b";
public static String TextToAnalyze;
public static String CopyOfText = "";
public static int ExaminatedIndex = 0;
public static List<String> ExtractedPhoneNumbers = new ArrayList<String>();
public static List<String> ExtractedIbanNumbers = new ArrayList<String>();
public static List<String> ExtractedAmounts = new ArrayList<String>();
public static List<String> ExtractedPostCodes = new ArrayList<String>();
public static final String EMPTY_STRING = "";
/**
* #brief Constructor: initializes the needed variables and call the different methods in order to find an classify the Numbers
*
* #param Text: is the input text that need to be analyzed
*/
public NumberExtractorAndClassifier(String Text) {
TextToAnalyze = Text; //- This variable is going to have our complete text
CopyOfText = Text; //- This variable is going to have the missing text to analyze
//- We extract the amounts first in order to do not confuse them later with a phone number, IBAN or post-code
ExtractedAmounts = ExtractAmounts();
for (String Amount : ExtractedAmounts)
{
//- We cut them out of the text in order to do not confuse them later with a IBAN, phone number or post-code
String safeToUseInReplaceAllString = Pattern.quote(Amount);
CopyOfText = CopyOfText.replaceAll(safeToUseInReplaceAllString, "");
System.out.println("Found amount -------> " + Amount);
}
//- We extract the IBAN secondly in order to do not confuse them later with a phone number or post-code
ExtractedIbanNumbers = ExtracIbanNumbers();
for (String Iban : ExtractedIbanNumbers)
{
//- We cut them out of the text in order to do not confuse them later with a phone number, or post-code
String safeToUseInReplaceAllString = Pattern.quote(Iban);
CopyOfText = CopyOfText.replaceAll(safeToUseInReplaceAllString, "");
System.out.println("Found IBAN ---------> " + Iban);
}
//- We extract the phone numbers thirdly in order to do not confuse them later with a post-code
ExtractedPhoneNumbers = ExtractPhoneNumbers();
for( String number : ExtractedPhoneNumbers )
{
//- We cut them out of the text in order to do not confuse them later with a post-code
String safeToUseInReplaceAllString = Pattern.quote(number);
CopyOfText = CopyOfText.replaceAll(safeToUseInReplaceAllString, "");
System.out.println("Found number -------> " + number);
}
ExtractedPostCodes = ExtractPostCodes();
for( String PostCode : ExtractedPostCodes)
{
System.out.println("Found post code ----> " + PostCode);
}
}
/**
* #Brief Method extracts phone numbers out of the text with help of REGEXPhoneNumbers
*
* #return List of strings with all the found numbers.
*/
public static List<String> ExtractPhoneNumbers(){
//Initializing our variables
List<String> FoundNumbers = new ArrayList<String>();
boolean LineContainsNumber = true;
Pattern pattern = Pattern.compile(REGEXPhoneNumbers);
Matcher matcher = pattern.matcher(CopyOfText);
while (LineContainsNumber) {
if (matcher.find()) {
String NumberFoundByTheMatcher = matcher.group(0);
FoundNumbers.add(NumberFoundByTheMatcher);
}
else{LineContainsNumber = false;}
}
return FoundNumbers;
}
/**
* #Brief Method extracts IBAN numbers out of the text with help of REGEXIbanNumbers
*
* #return List of strings with all the found IBANS numbers.
*/
public static List<String> ExtracIbanNumbers(){
//Initializing our variables
List<String> FoundIbans = new ArrayList<String>();
boolean LineContainsIban = true;
Pattern pattern = Pattern.compile(REGEXIbanNumbers);
Matcher matcher = pattern.matcher(CopyOfText);
while (LineContainsIban) {
if (matcher.find()) {
String NumberFoundByTheMatcher = matcher.group(0);
FoundIbans.add(NumberFoundByTheMatcher);
}
else{LineContainsIban = false;}
}
return FoundIbans;
}
/**
* #Brief Method extracts Amounts out of the text with help of REGEXAmounts
*
* #return List of strings with all the found amounts.
*/
public static List<String> ExtractAmounts(){
//Initializing our variables
List<String> FoundAmounts = new ArrayList<String>();
boolean LineContainsAmount = true;
Pattern pattern = Pattern.compile(REGEXAmounts);
Matcher matcher = pattern.matcher(CopyOfText);
while (LineContainsAmount) {
if (matcher.find()) {
String NumberFoundByTheMatcher = matcher.group(0);
FoundAmounts.add(NumberFoundByTheMatcher);
}
else{LineContainsAmount = false;}
}
return FoundAmounts;
}
/**
* #Brief Method extracts post codes out of the text with help of REGEXPostCode
*
* #return List of strings with all the found post codes.
*/
public static List<String> ExtractPostCodes(){
List<String> FoundPostCodes = new ArrayList<String>();
boolean LineContainsPostCode = true;
Pattern pattern = Pattern.compile(REGEXPostCode);
Matcher matcher = pattern.matcher(CopyOfText);
while(LineContainsPostCode) {
if(matcher.find()) {
String PostCodeFoundByMatcher = matcher.group(0);
FoundPostCodes.add(PostCodeFoundByMatcher);
}
else {
LineContainsPostCode = false;
}
}
return FoundPostCodes;
}
}
I've string like below , want to get the value of cn=ADMIN , but dont know how to get to using regex efficient way.
group:192.168.133.205:387/cn=ADMIN,cn=groups,dc=mi,dc=com,dc=usa
well ... like this?
package test;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexSample {
public static void main(String[] args) {
String str = "group:192.168.133.205:387/cn=ADMIN,cn=groups,dc=mi,dc=com,dc=usa";
Pattern pattern = Pattern.compile("^.*/(.*)$");
Matcher matcher = pattern.matcher(str);
if (matcher.matches()) {
String right = matcher.group(1);
String[] parts = right.split(",");
for (String part : parts) {
System.err.println("part: " + part);
}
}
}
}
Output is:
part: cn=ADMIN
part: cn=groups
part: dc=mi
part: dc=com
part: dc=usa
String bubba = "group:192.168.133.205:387/cn=ADMIN,cn=groups,dc=mi,dc=com,dc=usa";
String target = "cn=ADMIN";
for(String current: bubba.split("[/,]")){
if(current.equals(target)){
System.out.println("Got it");
}
}
Pattern for regex
cn=([a-zA-Z0-9]+?),
Your name will be in group 1 of matcher. You can extend character classes if you allow spaces etc.
I have the following code. I need to check the text for existing any of the words from some list of banned words. But even if this word exists in the text matcher doesn't see it. here is the code:
final ArrayList<String> regexps = config.getProperty(property);
for (String regexp: regexps){
Pattern pt = Pattern.compile("(" + regexp + ")", Pattern.CASE_INSENSITIVE);
Matcher mt = pt.matcher(plainText);
if (mt.find()){
result = result + "message can't be processed because it doesn't satisfy the rule " + property;
reason = false;
System.out.println("reason" + mt.group() + regexp);
}
}
What is wrong? This code can'f find regexp в[ыy][шs]лит[еe], which is regexp in the plainText = "Вышлите пожалуйста новый счет на оплату на Санг, пока согласовывали, уже
прошли его сроки. Лиценз...". I also tried another variants of the regexp but everything is useless
The trouble is elsewhere.
import java.util.regex.*;
public class HelloWorld {
public static void main(String []args) {
Pattern pt = Pattern.compile("(qwer)");
Matcher mt = pt.matcher("asdf qwer zxcv");
System.out.println(mt.find());
}
}
This prints out true. You may want to use word boundary as delimiter, though:
import java.util.regex.*;
public class HelloWorld {
public static void main(String []args) {
Pattern pt = Pattern.compile("\\bqwer\\b");
Matcher mt = pt.matcher("asdf qwer zxcv");
System.out.println(mt.find());
mt = pt.matcher("asdfqwer zxcv");
System.out.println(mt.find());
}
}
The parenthesis are useless unless you need to capture the keyword in a group. But you already have it to begin with.
Use ArrayList's built in functions indexOf(Object o) and contains(Object o) to check if a String exists anywhere in the Array and where.
e.g.
ArrayList<String> keywords = new ArrayList<String>();
keywords.add("hello");
System.out.println(keywords.contains("hello"));
System.out.println(keywords.indexOf("hello"));
outputs:
true
0
Try this to filter out messages which contain banned words using the following regex which uses OR operator.
private static void findBannedWords() {
final ArrayList<String> keywords = new ArrayList<String>();
keywords.add("f$%k");
keywords.add("s!#t");
keywords.add("a$s");
String input = "what the f$%k";
String bannedRegex = "";
for (String keyword: keywords){
bannedRegex = bannedRegex + ".*" + keyword + ".*" + "|";
}
Pattern pt = Pattern.compile(bannedRegex.substring(0, bannedRegex.length()-1));
Matcher mt = pt.matcher(input);
if (mt.matches()) {
System.out.println("message can't be processed because it doesn't satisfy the rule ");
}
}
I want to tokenize a string like this
String line = "a=b c='123 456' d=777 e='uij yyy'";
I cannot split based like this
String [] words = line.split(" ");
Any idea how can I split so that I get tokens like
a=b
c='123 456'
d=777
e='uij yyy';
The simplest way to do this is by hand implementing a simple finite state machine. In other words, process the string a character at a time:
When you hit a space, break off a token;
When you hit a quote keep getting characters until you hit another quote.
Depending on the formatting of your original string, you should be able to use a regular expression as a parameter to the java "split" method: Click here for an example.
The example doesn't use the regular expression that you would need for this task though.
You can also use this SO thread as a guideline (although it's in PHP) which does something very close to what you need. Manipulating that slightly might do the trick (although having quotes be part of the output or not may cause some issues). Keep in mind that regex is very similar in most languages.
Edit: going too much further into this type of task may be ahead of the capabilities of regex, so you may need to create a simple parser.
line.split(" (?=[a-z+]=)")
correctly gives:
a=b
c='123 456'
d=777
e='uij yyy'
Make sure you adapt the [a-z+] part in case your keys structure changes.
Edit: this solution can fail miserably if there is a "=" character in the value part of the pair.
StreamTokenizer can help, although it is easiest to set up to break on '=', as it will always break at the start of a quoted string:
String s = "Ta=b c='123 456' d=777 e='uij yyy'";
StreamTokenizer st = new StreamTokenizer(new StringReader(s));
st.ordinaryChars('0', '9');
st.wordChars('0', '9');
while (st.nextToken() != StreamTokenizer.TT_EOF) {
switch (st.ttype) {
case StreamTokenizer.TT_NUMBER:
System.out.println(st.nval);
break;
case StreamTokenizer.TT_WORD:
System.out.println(st.sval);
break;
case '=':
System.out.println("=");
break;
default:
System.out.println(st.sval);
}
}
outputs
Ta
=
b
c
=
123 456
d
=
777
e
=
uij yyy
If you leave out the two lines that convert numeric characters to alpha, then you get d=777.0, which might be useful to you.
Assumptions:
Your variable name ('a' in the assignment 'a=b') can be of length 1 or more
Your variable name ('a' in the assignment 'a=b') can not contain the space character, anything else is fine.
Validation of your input is not required (input assumed to be in valid a=b format)
This works fine for me.
Input:
a=b abc='123 456' &=777 #='uij yyy' ABC='slk slk' 123sdkljhSDFjflsakd#*#&=456sldSLKD)#(
Output:
a=b
abc='123 456'
&=777
#='uij yyy'
ABC='slk slk'
123sdkljhSDFjflsakd#*#&=456sldSLKD)#(
Code:
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class RegexTest {
// SPACE CHARACTER followed by
// sequence of non-space characters of 1 or more followed by
// first occuring EQUALS CHARACTER
final static String regex = " [^ ]+?=";
// static pattern defined outside so that you don't have to compile it
// for each method call
static final Pattern p = Pattern.compile(regex);
public static List<String> tokenize(String input, Pattern p){
input = input.trim(); // this is important for "last token case"
// see end of method
Matcher m = p.matcher(input);
ArrayList<String> tokens = new ArrayList<String>();
int beginIndex=0;
while(m.find()){
int endIndex = m.start();
tokens.add(input.substring(beginIndex, endIndex));
beginIndex = endIndex+1;
}
// LAST TOKEN CASE
//add last token
tokens.add(input.substring(beginIndex));
return tokens;
}
private static void println(List<String> tokens) {
for(String token:tokens){
System.out.println(token);
}
}
public static void main(String args[]){
String test = "a=b " +
"abc='123 456' " +
"&=777 " +
"#='uij yyy' " +
"ABC='slk slk' " +
"123sdkljhSDFjflsakd#*#&=456sldSLKD)#(";
List<String> tokens = RegexTest.tokenize(test, p);
println(tokens);
}
}
Or, with a regex for tokenizing, and a little state machine that just adds the key/val to a map:
String line = "a = b c='123 456' d=777 e = 'uij yyy'";
Map<String,String> keyval = new HashMap<String,String>();
String state = "key";
Matcher m = Pattern.compile("(=|'[^']*?'|[^\\s=]+)").matcher(line);
String key = null;
while (m.find()) {
String found = m.group();
if (state.equals("key")) {
if (found.equals("=") || found.startsWith("'"))
{ System.err.println ("ERROR"); }
else { key = found; state = "equals"; }
} else if (state.equals("equals")) {
if (! found.equals("=")) { System.err.println ("ERROR"); }
else { state = "value"; }
} else if (state.equals("value")) {
if (key == null) { System.err.println ("ERROR"); }
else {
if (found.startsWith("'"))
found = found.substring(1,found.length()-1);
keyval.put (key, found);
key = null;
state = "key";
}
}
}
if (! state.equals("key")) { System.err.println ("ERROR"); }
System.out.println ("map: " + keyval);
prints out
map: {d=777, e=uij yyy, c=123 456, a=b}
It does some basic error checking, and takes the quotes off the values.
This solution is both general and compact (it is effectively the regex version of cletus' answer):
String line = "a=b c='123 456' d=777 e='uij yyy'";
Matcher m = Pattern.compile("('[^']*?'|\\S)+").matcher(line);
while (m.find()) {
System.out.println(m.group()); // or whatever you want to do
}
In other words, find all runs of characters that are combinations of quoted strings or non-space characters; nested quotes are not supported (there is no escape character).
public static void main(String[] args) {
String token;
String value="";
HashMap<String, String> attributes = new HashMap<String, String>();
String line = "a=b c='123 456' d=777 e='uij yyy'";
StringTokenizer tokenizer = new StringTokenizer(line," ");
while(tokenizer.hasMoreTokens()){
token = tokenizer.nextToken();
value = token.contains("'") ? value + " " + token : token ;
if(!value.contains("'") || value.endsWith("'")) {
//Split the strings and get variables into hashmap
attributes.put(value.split("=")[0].trim(),value.split("=")[1]);
value ="";
}
}
System.out.println(attributes);
}
output:
{d=777, a=b, e='uij yyy', c='123 456'}
In this case continuous space will be truncated to single space in the value.
here attributed hashmap contains the values
import java.io.*;
import java.util.Scanner;
public class ScanXan {
public static void main(String[] args) throws IOException {
Scanner s = null;
try {
s = new Scanner(new BufferedReader(new FileReader("<file name>")));
while (s.hasNext()) {
System.out.println(s.next());
<write for output file>
}
} finally {
if (s != null) {
s.close();
}
}
}
}
java.util.StringTokenizer tokenizer = new java.util.StringTokenizer(line, " ");
while (tokenizer.hasMoreTokens()) {
String token = tokenizer.nextToken();
int index = token.indexOf('=');
String key = token.substring(0, index);
String value = token.substring(index + 1);
}
Have you tried splitting by '=' and creating a token out of each pair of the resulting array?
Is there any way to replace a regexp with modified content of capture group?
Example:
Pattern regex = Pattern.compile("(\\d{1,2})");
Matcher regexMatcher = regex.matcher(text);
resultString = regexMatcher.replaceAll("$1"); // *3 ??
And I'd like to replace all occurrence with $1 multiplied by 3.
edit:
Looks like, something's wrong :(
If I use
Pattern regex = Pattern.compile("(\\d{1,2})");
Matcher regexMatcher = regex.matcher("12 54 1 65");
try {
String resultString = regexMatcher.replaceAll(regexMatcher.group(1));
} catch (Exception e) {
e.printStackTrace();
}
It throws an IllegalStateException: No match found
But
Pattern regex = Pattern.compile("(\\d{1,2})");
Matcher regexMatcher = regex.matcher("12 54 1 65");
try {
String resultString = regexMatcher.replaceAll("$1");
} catch (Exception e) {
e.printStackTrace();
}
works fine, but I can't change the $1 :(
edit:
Now, it's working :)
How about:
if (regexMatcher.find()) {
resultString = regexMatcher.replaceAll(
String.valueOf(3 * Integer.parseInt(regexMatcher.group(1))));
}
To get the first match, use #find(). After that, you can use #group(1) to refer to this first match, and replace all matches by the first maches value multiplied by 3.
And in case you want to replace each match with that match's value multiplied by 3:
Pattern p = Pattern.compile("(\\d{1,2})");
Matcher m = p.matcher("12 54 1 65");
StringBuffer s = new StringBuffer();
while (m.find())
m.appendReplacement(s, String.valueOf(3 * Integer.parseInt(m.group(1))));
System.out.println(s.toString());
You may want to look through Matcher's documentation, where this and a lot more stuff is covered in detail.
earl's answer gives you the solution, but I thought I'd add what the problem is that's causing your IllegalStateException. You're calling group(1) without having first called a matching operation (such as find()). This isn't needed if you're just using $1 since the replaceAll() is the matching operation.
Java 9 offers a Matcher.replaceAll() that accepts a replacement function:
resultString = regexMatcher.replaceAll(
m -> String.valueOf(Integer.parseInt(m.group()) * 3));
Source: java-implementation-of-rubys-gsub
Usage:
// Rewrite an ancient unit of length in SI units.
String result = new Rewriter("([0-9]+(\\.[0-9]+)?)[- ]?(inch(es)?)") {
public String replacement() {
float inches = Float.parseFloat(group(1));
return Float.toString(2.54f * inches) + " cm";
}
}.rewrite("a 17 inch display");
System.out.println(result);
// The "Searching and Replacing with Non-Constant Values Using a
// Regular Expression" example from the Java Almanac.
result = new Rewriter("([a-zA-Z]+[0-9]+)") {
public String replacement() {
return group(1).toUpperCase();
}
}.rewrite("ab12 cd efg34");
System.out.println(result);
Implementation (redesigned):
import static java.lang.String.format;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public abstract class Rewriter {
private Pattern pattern;
private Matcher matcher;
public Rewriter(String regularExpression) {
this.pattern = Pattern.compile(regularExpression);
}
public String group(int i) {
return matcher.group(i);
}
public abstract String replacement() throws Exception;
public String rewrite(CharSequence original) {
return rewrite(original, new StringBuffer(original.length())).toString();
}
public StringBuffer rewrite(CharSequence original, StringBuffer destination) {
try {
this.matcher = pattern.matcher(original);
while (matcher.find()) {
matcher.appendReplacement(destination, "");
destination.append(replacement());
}
matcher.appendTail(destination);
return destination;
} catch (Exception e) {
throw new RuntimeException("Cannot rewrite " + toString(), e);
}
}
#Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(pattern.pattern());
for (int i = 0; i <= matcher.groupCount(); i++)
sb.append(format("\n\t(%s) - %s", i, group(i)));
return sb.toString();
}
}