I am trying to split a line with regex by using groups, but it's not working as I expected.
I want to match for example this line:
Ex. #1: temp name(this is the data)
and also this:
Ex. #2: temp name()
I used this regex:
[\s]*temp[\s]+[\s]*([A-Za-z]+)[\s]*[(]\s*(.*)+[)]\s*[{]\s*
which means: grab anything that starts with temp then put in group #1 the "name" then grab whatever inside the bracket and put it in group #2.
However, group #2 is always empty.
This is my code to fetch the data:
Pattern PATTERN = Pattern.compile("[\\s]*temp[\\s]+[\\s]*([A-Za-z]+)[\\s]*[(]\\s*(.*)+[)]\\s*");
Matcher m = PATTERN.matcher("temp name(this is the data)");
m.matches();
String name = m.group(1);
String data = m.group(2); // always empty
What am I doing wrong?
Your pattern doesn't match because it requires an open curly brace at the end, but your input doesn't have one.
Ignoring that small problem, the main problem is the little + after your capture group (.*)+. The plus requires one or more matches of .* and the group returned is the last match of the many. The term .* is greedy, so it consumes everything up to the bracket. The only way to match again is to consume nothing. So the last match of group 2 is blank.
To fix it, remove the + after group 2:
Pattern PATTERN = Pattern.compile("\\s*temp\\s+([A-Za-z]+)\\s*[(]\\s*(.*)[)]\\s*");
Note also how I removed other unnecessary characters from your regex, eg the single-character character classes - ie [\\s] is identical to \s. And \\s+\\s* is identical to just \\s+, because + is greedy.
I also removed the trailing curly bracket, which you can restore if your input data actually has it (your question showed input of "temp name(this is the data)", which has no trailing curly bracket).
Your regex should be this:
Pattern pattern = Pattern.compile("\\s*temp\\s+([A-Za-z]+)\\s*[(]\\s*(.*)[)]\\s*");
You had (.*)+ which means one or more matches of .*. This results in nothing being captured.
Testing:
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Example {
public static void main(String[] args) {
Pattern pattern = Pattern.compile("\\s*temp\\s+([A-Za-z]+)\\s*[(]\\s*(.*)[)]\\s*");
Matcher m = pattern.matcher("temp name(this is the data)");
if(m.matches()) {
System.out.println(m.group(1));
System.out.println(m.group(2));
}
}
}
Output:
name
this is the data
[\s] is equivalent with \s
[\s]+[\s]* is equivalent with \s+
[(] is equivalent with \( (same for [)] and [}])
This would leave your regexp as:
\s*temp\s+([A-Za-z]+)\s*\(\s*(.*)+\)\s*\{\s*
Assuming you actually want to match temp name(...) { (your regexp is looking for a {, while in your question you do not specify that):
(.*)+ is your problem. You're saying: "Match any number (including 0) chatacters and put them in a capture group, repeat that at least once".
Regexp are by default greedy (= they consume as much as possible), so the capture group will first contain everything within the two brackets, then the + will try to match the entire group again, and will match it with "" (the emtpy string) as this fulfils the capture group's pattern. This will elave your capture group emtpy.
What you want instead is \s*temp\s+([A-Za-z]+)\s*\(\s*(.*)\)\s*\{\s*
The reason you are getting empty groups is because you are creating multiple capture groups every time you put something between (), even if it is nested.
To make a group so it doesnt capture you can designate it as a non-capturing group by using ?: for example (?:sometest(this is the value we want)) will return just one group while (sometest(this is the value we want)) will return 2 groups.
For your particular regex, I have refined and simplified it, as you had capture groups you did not need.
Simple solution:
\\s*temp\\s+([A-Za-z]+)\\s*\\(\\s*(.*)\\)\\s*\{\\s*
given the input:
Ex. #1: temp name(this is the data) {
Ex. #2: temp name() {
$1 = name, $2 = data
Pay attention to the fact that your regex contains a trailing curly brace. You can modify the regex to match without it and it will result in this:
\\s*temp\\s+([A-Za-z]+)\\s*\\(\\s*(.*)\\)\\s*
https://regex101.com/r/tD0tO0/1
Related
I am working on Pentaho which uses Java regex package : java.util.regex.
I want to extract a lot of information from the lines of a text file from both start and end of the string :
^StartofString Controls\(param1="(D[0-9]{0,})",param2="(G[0-9]{0,})",param3="([^"]{0,})",param4="([^"]{0,})"\):(?:.*)param5="([^"]{0,})",.*
There is a long part of the string I want to ignore and try to do so with (?:.*)
The positive lookahead seems working when I test the Regex on the step but does not work when I execute the transformation.
I test the string on 'Regex Evaluation' step, check with 'Filter rows' the boolean of previous step and extract groups within a Javascript step :
var pattern = Packages.java.util.regex.Pattern.compile(patternStr);
var matcher = pattern.matcher(content.toString());
var matchFound = matcher.find();
with patterStr being the same regex than the one in the 'Regex Evaluation' step but with escaping characters : \
I have read many questions about ignoring parts of strings in regex and still can't find the answer.
Any help is welcome.
I can provide more informations if needed.
A non capturing group doesn't mean that its content won't be captured, it means that it won't be captured in a group (although you're still grouping tokens in your regex, which can be useful to apply a modifier to them at once).
For example, these regex will all match the exact same abc string :
abc
a(?:b)c
a(b)c
However in the third case, you've defined a capturing group which will enable you to access to b independently. The first two cases are equals in all respects.
The non-capturing group becomes useful when you want to apply a modifier to a group of tokens without having an extra group you can reference later. The following regexs will all match the same strings :
(ab)*(c)\2
(?:ab)*(c)\1
We want to apply * to the ab tokens. Either we do it with a capturing group (first example) and a group is created that we can reference, or we use a non-capturing group. The backreference at the end of the regex is supposed to match the c ; in the first example it's the second group since ab is the first one, while in the second c is the first group that can be referenced.
Now that I've explained what non-capturing groups do, let's solve your problem : you want to remove something from the middle of your string, where you know what's at the beginning and what's at the end.
Let's assume the string you want to match is the following :
Aremove-thisB
And that you want the result AB.
There are multiple strategies to do so, the easiest in your case probably is to match both the beginning and end of the string in their own capturing group and create your output from there :
var pattern = Packages.java.util.regex.Pattern.compile("(A).*(B)");
var matcher = pattern.matcher(content.toString());
var matchFound = matcher.find();
if (matchFound) { return matcher.group(1) + matcher.group(2); }
Hi I am trying to do regex in java, I need to capture the last {n} words. (There may be a variable num of whitespaces between words). Requirement is it has to be done in regex.
So e.g. in
The man is very tall.
For n = 2, I need to capture
very tall.
So I tried
(\S*\s*){2}$
But this does not match in java because the initial words have to be consumed first. So I tried
^(.*)(\S*\s*){2}$
But .* consumes everything, and the last 2 words are ignored.
I have also tried
^\S?\s?(\S*\s*){2}$
Anyone know a way around this please?
You had almost got it in your first attempt.
Just change + to *.
The plus sign means at least one character, because there wasn't any space the match had failed.
On the other hand the asterisk means from zero to more, so it will work.
Look it live here: (?:\S*\s*){2}$
Using replaceAll method, you could try this regex: ((?:\\S*\\s*){2}$)|.
Your regex contains - as you already mention - a greedy subpattern that eats up the whole string and sine (\S*\s*){2} can match an empty string, it matches an empty location at the end of the input string.
Lazy dot matching (changing .* to .*?) won't do the whole job since the capturing group is quantified, and the Matcher.group(1) will be set to the last captured non-whitespaces with optional whitespaces. You need to set the capturing group around the quantified group.
Since you most likely are using Matcher#matches, you can use
String str = "The man is very tall.";
Pattern ptrn = Pattern.compile("(.*?)((?:\\S*\\s*){2})"); // no need for `^`/`$` with matches()
Matcher matcher = ptrn.matcher(str);
if (matcher.matches()) { // Group 2 contains the last 2 "words"
System.out.println(matcher.group(2)); // => very tall.
}
See IDEONE demo
I am trying to match a string that looks like "WIFLYMODULE-xxxx" where the x can be any digit. For example, I want to be able to find the following...
WIFLYMODULE-3253
WIFLYMODULE-1585
WIFLYMODULE-1632
I am currently using
final Pattern q = Pattern.compile("[WIFLYMODULE]-[0-9]{3}");
but I am not picking up the string that I want. So my question is, why is my regular expression not working? Am i going about it in the wrong way?
You should use (..) instead of [...]. [..] is used for Character class
With a "character class", also called "character set", you can tell the regex engine to match only one out of several characters.
(WIFLYMODULE)-[0-9]{4}
Here is demo
Note: But in this case it's not needed at all. (...) is used for capturing group to access it by Matcher.group(index)
Important Note: Use \b as word boundary to match the correct word.
\\bWIFLYMODULE-[0-9]{4}\\b
Sample code:
String str = "WIFLYMODULE-3253 WIFLYMODULE-1585 WIFLYMODULE-1632";
Pattern p = Pattern.compile("\\bWIFLYMODULE-[0-9]{4}\\b");
Matcher m = p.matcher(str);
while (m.find()) {
System.out.println(m.group());
}
output:
WIFLYMODULE-3253
WIFLYMODULE-1585
WIFLYMODULE-1632
The regex should be:
"WIFLYMODULE-[0-9]{4}"
The square brackets means: one of the characters listed inside. Also you were matching three numbers instead of four. So your were matching strings like (where xxx is a number of three digits):
W-xxx, I-xxx, F-xxx, L-xxx, Y-xxx, M-xxx, O-xxx, D-xxx, U-xxx, L-xxx, E-xxx
You had it match on 3 digits instead of 4. And putting WIFLYMODULE inside [] makes it match on only one of those characters.
final Pattern q = Pattern.compile("WIFLYMODULE-[0-9]{4}");
[...] means that one character out of the ones in the bracket must match and not the string within it.
You, however, want to match WIFLYMODULE, thus, you have to use Pattern.compile("WIFLYMODULE-[0-9]{3}"); or Pattern.compile("(WIFLYMODULE)-[0-9]{3}");
{n} means that the character (or group) must match n-times. In your example you need 4 instead of 3: Pattern.compile("WIFLYMODULE-[0-9]{4}");
This way will work:
final Pattern q = Pattern.compile("WIFLYMODULE-[0-9]{4}");
The pattern breaks down to:
WIFLYMODULE- The literal string WIFLYMODULE-
[0-9]{4} Exactly four digits
What you had was:
[WIFLYMODULE] Any one of the characters in WIFLYMODULE
- The literal string -
[0-9]{3} Exactly three digits
I have a String like this : String x = "return function ('ABC','DEF')";
I am using this:
Pattern pattern = Pattern.compile("'(.*?)'");
Matcher matcher = pattern.matcher(formula);
while (matcher.find()) {
System.out.println("------> " + matcher.group();
}
to retrieve strings between single quotes.
My question is: how can i adapt this regex so that it will check for strings between single quotes AND strings like " ,'DEF' " (meaning which start with ,' and end with ')?
You can use this pattern:
'[^']+'|"[^"]+"
Just to match with empty quoted string change '+' to '*'.
See test.
This pattern should do what you want:
"(?:,\s*)?'[^']*'"
The ? means the first group will match zero or one times.
I used (?:...) because this is a non-capturing group. It is better to use when you don't need to capture that portion of the match.
Also, I replaced .*? with [^']*, meaning the single-quoted string contains anything that is not a single quote. This is more efficient and less likely to lead to mistakes in your regex than .*?.
(Note: this regex allows there to be space between the comma and the start of the string. At first looking at your example, I thought that was true of your example. But now I see that it is not. Still, that might be useful depending on what your data looks like).
You could use the regex pattern:
Pattern.compile(",?'(.*?)'");
,? means 0 or 1 commas. The ? is greedy, so if there is a comma, it will be included in the match.
So: This will match:
A comma, followed by a string enclosed in single quotes
OR.. only a string enclosed in single quotes
I would like to match:
some.name.separated.by.dots
But I don't have any idea how.
I can match a single part like this
\w+\.
How can I say "repeat that"
Try the following:
\w+(?:\.\w+)+
The + after (?: ... ) tell it to match what is inside the parenthesis one or more times.
Note that \w only matches ASCII characters, so a word like café wouldn't be matches by \w+, let alone words/text containing Unicode.
EDIT
The difference between [...] and (?:...) is that [...] always matches a single character. It is called a "character set" or "character class". So, [abc] does not match the string "abc", but matches one of the characters a, b or c.
The fact that \w+[\.\w+]* also matches your string is because [\.\w+] matches a . or a character from \w, which is then repeated zero or more time by the * after it. But, \w+[\.\w+]* will therefor also match strings like aaaaa or aaa............
The (?:...) is, as I already mentioned, simply used to group characters (and possible repeat those groups).
More info on character sets: http://www.regular-expressions.info/charclass.html
More info on groups: http://www.regular-expressions.info/brackets.html
EDIT II
Here's an example in Java (seeing you post mostly Java answers):
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class Main {
public static void main(String[] args) {
String text = "some.text.here only but not Some other " +
"there some.name.separated.by.dots and.we are done!";
Pattern p = Pattern.compile("\\w+(?:\\.\\w+)+");
Matcher m = p.matcher(text);
while(m.find()) {
System.out.println(m.group());
}
}
}
which will produce:
some.text.here
some.name.separated.by.dots
and.we
Note that m.group(0) and m.group() are equivalent: meaning "the entire match".
This will also work:
(\w+(\.|$))+
You can use ? to match 0 or 1 of the preceeding parts, * to match 0 to any amount of the preceeding parts, and + to match at least one of the preceeding parts.
So (\w\.)? will match w. and a blank, (\w\.)* will match r.2.5.3.1.s.r.g.s. and a blank, and (\w\.)+ will match any of the above but not a blank.
If you want to match something like your example, you'll need to do (\w+\.)+, which means 'match at least one non whitespace, then a period, and match at least one of these'.
(\w+\.)+
Apparently, the body has to be at least 30 characters. I hope this is enough.