In Full Match you get everything that regex says about, even non-capturing groups. You need to get appropriate Match to get rid of non-capturing groups. The other solution is to use positive lookahead instead of capturing group. Check the regex below. I also removed some unnecessary (IMO) groups.
(?:Bundle\s+Components|Included\s+Components)\s+.*?(?=Bundle)
It results with only one, full, match.
Demo
PS: The sign of new line just before "Bundle" will be captured as well in this solution.
Answer from Egan Wolf on Stack OverflowNon-capturing group in java RegEx - Stack Overflow
Java Regex Non-Capturing Group - Stack Overflow
Non capturing group java regex - Stack Overflow
java - regular expressions: quantifying a non-capturing group - Stack Overflow
In Full Match you get everything that regex says about, even non-capturing groups. You need to get appropriate Match to get rid of non-capturing groups. The other solution is to use positive lookahead instead of capturing group. Check the regex below. I also removed some unnecessary (IMO) groups.
(?:Bundle\s+Components|Included\s+Components)\s+.*?(?=Bundle)
It results with only one, full, match.
Demo
PS: The sign of new line just before "Bundle" will be captured as well in this solution.
You can do this with positive lookahead, since with this one the pattern inside the lookahead group is not included in the match:
((?:Bundle\\s+Components)|(?:Included\\s+Components))\\s+(.*?)(?=Bundle)
(not tested)
You need to make the String part optional by using a ?:
String regexFilter = "(?:String )?(Transformation) (Action)";
Also, there isn't much point in putting capturing groups around literal text (e.g. Transformation and Action) since you always know what those groups will capture.
String regexFilter = "(?:String )?Transformation Action";
Make String part optional using this regex:
String regexFilter = "\\b(?:String )?Transformation Action\\b";
PS: I have also added \\b (word boundary) to make your don't match Transformation Action111 OR xyzTransformation Action type strings.
It means that the grouping is atomic, and it throws away backtracking information for a matched group. So, this expression is possessive; it won't back off even if doing so is the only way for the regex as a whole to succeed. It's "independent" in the sense that it doesn't cooperate, via backtracking, with other elements of the regex to ensure a match.
I think this tutorial explains what exactly "independent, non-capturing group" or "Atomic Grouping" is
The regular expression
a(bc|b)c(capturing group) matches abcc and abc. The regexa(?>bc|b)c(atomic group) matches abcc but not abc.When applied to abc, both regexes will match
ato a,bcto bc, and thencwill fail to match at the end of the string. Here their paths diverge. The regex with the capturing group has remembered a backtracking position for the alternation. The group will give up its match,bthen matches b andcmatches c. Match found!The regex with the atomic group, however, exited from an atomic group after
bcwas matched. At that point, all backtracking positions for tokens inside the group are discarded. In this example, the alternation's option to trybat the second position in the string is discarded. As a result, whencfails, the regex engine has no alternatives left to try.
Why not use look-ahead / look-behind instead?
They are non-capturing and would work easily here:
str = str
.replaceAll(
"(?<=\\[assembly: AssemblyVersion\\(\"\\d\\.\\d\\.).*(?=\"\\)\\])",
"4.0"
);
As an alternative to a look-behind, you can use capturing groups around what you want to keep, and keep what you want to replace in a non-capturing group or no group at all:
String str="[assembly: AssemblyVersion(\"1.0.0.0\")]";
str=str.replaceAll("(\\[assembly:\\s*AssemblyVersion\\(\"\\d+\\.\\d+\\.)\\d+\\.\\d+(?=\"\\)\\])", "$014.0");
System.out.println(str);
See IDEONE demo
Hi everyone!
I'm struggling to understand what are non-capturing groups.
My take and if I understood correctly:
-
when you group, you're applying precedence in terms of evaluation, like normal parenthesis would work in a math expression.
-
a normal group it creates some sort of indexing that the regex engine can use for other checks later on if it has advanced stuff like tagging or recursion.
-
when you use
?:- non-capturing group - you're also grouping as well but it doesn't do any indexing.
Is this correct?
Would there any difference between simple stuff like (^$)|(^(No|Yes)$) to (?:^$)|(?:^(?:No|Yes)$) ?
Thank you in advance.
Let me try to explain this with an example.
Consider the following text:
http://stackoverflow.com/
https://stackoverflow.com/questions/tagged/regex
Now, if I apply the regex below over it (I did not escape the slashes for clarity; when using it, slashes would have to be escaped to \/ )...
(https?|ftp)://([^/\r\n]+)(/[^\r\n]*)? // slashes not escaped for clarity
(https?|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)? // slashes escaped
... I would get the following result:
Match "http://stackoverflow.com/"
Group 1: "http"
Group 2: "stackoverflow.com"
Group 3: "/"
Match "https://stackoverflow.com/questions/tagged/regex"
Group 1: "https"
Group 2: "stackoverflow.com"
Group 3: "/questions/tagged/regex"
But I don't care about the protocol -- I just want the host and path of the URL. So, I change the regex to include the non-capturing group (?:).
(?:https?|ftp):\/\/([^/\r\n]+)(\/[^\r\n]*)? // slashes escaped
Now, my result looks like this:
Match "http://stackoverflow.com/"
Group 1: "stackoverflow.com"
Group 2: "/"
Match "https://stackoverflow.com/questions/tagged/regex"
Group 1: "stackoverflow.com"
Group 2: "/questions/tagged/regex"
See? The first group has not been captured. The parser uses it to match the text, but ignores it later, in the final result.
EDIT:
As requested, let me try to explain groups too.
Well, groups serve many purposes. They can help you to extract exact information from a bigger match (which can also be named), they let you rematch a previous matched group, and can be used for substitutions. Let's try some examples, shall we?
Imagine you have some kind of XML or HTML (be aware that regex may not be the best tool for the job, but it is nice as an example). You want to parse the tags, so you could do something like this (I have added spaces to make it easier to understand):
\<(?<TAG>.+?)\> [^<]*? \</\k<TAG>\>
or
\<(.+?)\> [^<]*? \</\1\>
The first regex has a named group (TAG), while the second one uses a common group. Both regexes do the same thing: they use the value from the first group (the name of the tag) to match the closing tag. The difference is that the first one uses the name to match the value, and the second one uses the group index (which starts at 1).
Let's try some substitutions now. Consider the following text:
Lorem ipsum dolor sit amet consectetuer feugiat fames malesuada pretium egestas.
Now, let's use this dumb regex over it:
\b(\S)(\S)(\S)(\S*)\b
This regex matches words with at least 3 characters, and uses groups to separate the first three letters. The result is this:
Match "Lorem"
Group 1: "L"
Group 2: "o"
Group 3: "r"
Group 4: "em"
Match "ipsum"
Group 1: "i"
Group 2: "p"
Group 3: "s"
Group 4: "um"
...
Match "consectetuer"
Group 1: "c"
Group 2: "o"
Group 3: "n"
Group 4: "sectetuer"
...
So, if we apply the substitution string:
$1_$3$2_$4
... over it, we are trying to use the first group, add an underscore, use the third group, then the second group, add another underscore, and then the fourth group. The resulting string would be like the one below.
L_ro_em i_sp_um d_lo_or s_ti_ a_em_t c_no_sectetuer f_ue_giat f_ma_es m_la_esuada p_er_tium e_eg_stas.
You can use named groups for substitutions too, using ${name}.
To play around with regexes, I recommend http://regex101.com/, which offers a good amount of details on how the regex works; it also offers a few regex engines to choose from.
You can use capturing groups to organize and parse an expression. A non-capturing group has the first benefit, but doesn't have the overhead of the second. You can still say a non-capturing group is optional, for example.
Say you want to match numeric text, but some numbers could be written as 1st, 2nd, 3rd, 4th,... If you want to capture the numeric part, but not the (optional) suffix you can use a non-capturing group.
([0-9]+)(?:st|nd|rd|th)?
That will match numbers in the form 1, 2, 3... or in the form 1st, 2nd, 3rd,... but it will only capture the numeric part.