I have a string expression from which I need to get some values. The string is as follows
#min({(((fields['example6'].value + fields['example5'].value) * ((fields['example1'].value*5)+fields['example2'].value+fields['example3'].value-fields['example4'].value)) * 0.15),15,9.087})
From this stribg, I need to obtain a string array list which contains the values such as "example1", "example2" and so on.
I have a Java method which looks like this:
String regex = "/fields\\[['\"]([\\w\\s]+)['\"]\\]/g";
ArrayList<String> arL = new ArrayList<String>();
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(expression);
while(m.find()){
arL.add(m.group());
}
But m.find() always returns false. Is there anything I'm missing?
The problem is with the '/'s. If what you want to extract is only the field name, you should use m.group(1):
String regex = "fields\\[['\"]([\\w\\s]+)['\"]\\]";
ArrayList<String> arL = new ArrayList<String>();
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(expression);
while(m.find()){
arL.add(m.group(1));
}
The main issue you seem to have is that you are using delimiters (as in PHP or Perl or JavaScript) that cannot be used in a Java regex. Also, you have your matches in the first capturing group, but you are using group() that returns the whole match (including fields[').
Here is a working code:
String str = "#min({(((fields['example6'].value + fields['example5'].value) * ((fields['example1'].value*5)+fields['example2'].value+fields['example3'].value-fields['example4'].value)) * 0.15),15,9.087})";
ArrayList<String> arL = new ArrayList<String>();
String rx = "(?<=fields\\[['\"])[\\w\\s]*(?=['\"]\\])";
Pattern ptrn = Pattern.compile(rx);
Matcher m = ptrn.matcher(str);
while (m.find()) {
arL.add(m.group());
}
Here is a working IDEONE demo
Note that I have added look-arounds to extract just the texts between 's with group().
Related
I am running into an issue where my code is unable to find regex occurrences. Code:
String content = "This\ is\ an\ example.=This is an example\nThis\ is\ second\:=This is second"
String regex = "\"^.*(?=\\=)\"gm";
Pattern p = Pattern.compile(regex);
Matcher m = p.matcher(content);
List<String> mKeys = new ArrayList<>();
while (m.find()) {
mKeys.add(m.group());
}
mKeys turns out to be empty. I have already validated my regex here https://regex101.com/r/YResRc/3. I am expecting the list to contain two keys from the content.
Your content contains no " quotes, and no text gm, so why would you expect that regex to match?
FYI: Syntaxes like "foo"gm or /foo/gm are something other languages do for regex literals. Java doesn't do that.
The g flag is implied by the fact that you're using a find() loop, and m is the MULTILINE flag that affects ^ and $ and you can specify that using the (?m) pattern, or by adding a second parameter to compile(), i.e. one of these ways:
Pattern p = Pattern.compile("foo", Pattern.MULTILINE);
Pattern p = Pattern.compile("(?m)foo");
Your regex should simply be:
(?m)^.*(?==)
which means: Match everything from the beginning of a line up to the last = sign on the line.
Test
String content = "This is an example.=This is an example\nThis is second:=This is second";
String regex = "(?m)^.*(?==)";
Matcher m = Pattern.compile(regex).matcher(content);
List<String> mKeys = new ArrayList<>();
while (m.find()) {
mKeys.add(m.group());
}
System.out.println(mKeys);
Output
[This is an example., This is second:]
For e.g. get sub string of 3 characters after "abc".
abcxyzabcpqrabclmnoabcdef
output should be
xyz
prq
lmn
def
I am able to fetch only first occurrence but not all.
Here is a regex to do this:
(?<=abc)...
(?<=abc) means to only match the pattern after it if the characters abc is present before it. And the ... means to match 3 of any character.
final String regex = "(?<=abc)...";
final String string = "abcxyzabcpqrabclmnoabcdef";
final Pattern pattern = Pattern.compile(regex);
final Matcher matcher = pattern.matcher(string);
while (matcher.find()) {
System.out.println(matcher.group(0));
}
Try with following code snipped, it would work for you.
String str="abcxyzabcpqrabclmnoabcdef";
String[] strCsv=str.split("abc");
for(int i=0;i<strCsv.length;i++){
String str1=strCsv[i];
if(str1.length()>=3)
{
System.out.println(str1.substring(0,3));
}
}
Say for example I have the following string with a named capture group:
/this/(?<capture1>.*)/a/string/(?<capture2>.*)
And I want to replace the capture group with a value like "foo" so that I end up with a string that looks like:
/this/foo/a/string/bar
Limitations are:
Regex must be used as the string is evaluated elsewhere but it doesn't have to be a capture group.
I'd rather not have to regex match the regex.
EDIT: There can be many groups in the string.
You can find the starting and ending index
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
startindex= matcher.start();
stopindex=matcher.end();
// Your code for replacing that index and generating a new string with foo
// you can use string buffer to delete and insert the characters as you know the indexes
}
}
Full Implementation:
public static String getnewString(String text,String reg){
StringBuffer result = new StringBuffer(text);
Pattern pattern = Pattern.compile(reg);
Matcher matcher = pattern.matcher(text);
while (matcher.find()) {
int startindex= matcher.start();
int stopindex=matcher.end();
System.out.println(startindex+" "+stopindex);
result.delete(startindex, stopindex);
result.insert(startindex, "foo");
}
return result.toString();
}
Try this,
int lastIndex = s.lastIndexOf("/");
String newString = s.substring(0, lastIndex+1).concat("newString");
System.out.println(newString);
Get the subString till last '/' and then add new string to the substring like above
I got it:
String string = "/this/(?<capture1>.*)/a/string/(?<capture2>.*)";
Pattern pattern = Pattern.compile(string);
Matcher matcher = pattern.matches(string);
string.replace(matcher.group("capture1"), "value 1");
string.replace(matcher.group("capture2"), "value 2");
Crazy, but works.
Im having a hard time at a at writing a method that extracts words from a sentence. The words should start with aAeEiIoOuU and are 5 letters long for example ether.
The method should return a String array.My problem here is that I want that the length of the array is the same as the foudn words. If it found 3 words the array length should be 3 too.
This is my code at the moment:
public static String[] extractWords(String text){
String text = "einer hallo hallo einer";
String pattern = "\\b[AaEeIiOoUu]\\p{L}\\p{L}\\p{L}\\p{L}\\b";
Pattern p = Pattern.compile(pattern, Pattern.UNICODE_CASE);
Matcher m = p.matcher(text);
int i = 0;
while (m.find()){
i++;
}
String[] array = new String[i];
while(m.find()){
System.out.println(m.group());
array[i] = m.group();
i++;
}
}
You should be using ArrayList here. To use array, you have to do the matching twice, which is unnecessary extra work.
Also, just so you know, the second while(m.find()) loop, will not run even once, because the matcher has been exhausted by the first loop. You would need to re-initialize the Matcher object:
Matcher m = p.matcher(text); // Needed before second while loop.
But that is not needed. Let's use an ArrayList instead:
public static String[] extractWords(String text){
String text = "einer hallo hallo einer";
// Use quantifier to match 4 characters, instead of repeating it 4 times.
String pattern = "\\b[AaEeIiOoUu]\\p{L}{4}\\b";
Pattern p = Pattern.compile(pattern, Pattern.UNICODE_CASE);
Matcher m = p.matcher(text);
List<String> matchedWords = new ArrayList<>();
while (m.find()){
matchedWords.add(m.group());
}
// If you want an array, convert the list to array
String[] matchedWordArray = matchedWords.toArray(new String[matchedWords.size()]);
}
If I have,
String str = "11";
Pattern p = Pattern.compile("(\\d)\\1");
Matcher m = p.matcher(str);
How do I store use the result of \1 later? For example I want to do,
String str = "123123";
Pattern p = Pattern.compile("(\\d)\\1");
Matcher m = p.matcher(str);
String dependantString = //make this whatever was in group 1 of the pattern.
Is that possible?
You need to first call Matcher#find and then Matcher#group(1) like this:
String str = "123123";
Pattern p = Pattern.compile("(\\d+)\\1");
Matcher m = p.matcher(str);
if (m.find())
System.out.println( m.group(1) ); // 123
PS: Your regex also needed some correction to use \\d+ instead of \\d.