Cannot match parentheses in regex group - c#

This is a regular expression, evaluated in .NET
I have the following input:
${guid->newguid()}
And I want to produce two matching groups, a character sequence after the ${ and before }, which are split by -> :
guid
newguid()
The pattern I am using is the following:
([^(?<=\${)(.*?)(?=})->]+)
But this doesn't match the parentheses, I am getting only the following matches:
guid
newguid
How can I modify the regex so I get the desired groups?

Your regex - ([^(?<=\${)(.*?)(?=})->]+) - match 1+ characters other than those defined in the negated character class (that is, 1 or more chars other than (, ?, <, etc).
I suggest using a matching regex like this:
\${([^}]*?)->([^}]*)}
See the regex demo
The results you need are in match.Groups[1] and match.Groups[2].
Pattern details:
\${ - match ${ literal character sequence
([^}]*?) - Group 1 capturing 0+ chars other than } as few as possible
-> - a literal char sequence ->
([^}]*) - Group 2 capturing 0+ chars other than } as many as possible
} - a literal }.
If you know that you only have word chars inside, you may simplify the regex to a mere
\${(\w+)->(\w+\(\))}
See the regex demo. However, it is much less generic.

Your input structure is always ${identifier->identifier()}? If this is the case, you can user ^\$\{([^-]+)->([^}]+)\}$.
Otherwise, you can modify your regexpr to ([^?<=\${.*??=}\->]+): using this rexexpr you should match input and get the desired groups: uid and newguid(). The key change is the quoting of - char, which is intendend as range operator without quoting and forces you to insert parenthesis in your pattern - but... [^......(....)....] excludes parenthesis from the match.
I hope than can help!
EDIT: testing with https://regex101.com helped me a lot... showing me that - was intended as range operator.

Related

Regular expression to match capture group not preceded by certain characters

I want to write a regex that will match if and only if the pattern is not preceded by the characters "Etc/".
Strings that should match:
GMT+01:00
UTC+01:00
UTC+01
+01:00
...
Strings that should not match:
Etc/GMT+01:00
Etc/UTC+01:00
Etc/UTC+01
...
This is what I have so far:
(?<!Etc\/)((UTC|GMT)?(\+|\-){1}(\d{1,2})(:|\.)?(\d{1,2})?)
The right part of the above regular expression already matches the UTC and GMT offset and covers all the cases I need. But I don't manage to implement the exceptions mentioned above.
I expected the above regex to not match the string Etc/GMT+1:00. But in fact it matches the part +01:00 and only ignores Etc/GMT.
How can I achieve that the the following regular expression does not match if it is preceded with "Etc/"?
(UTC|GMT)?(\+|\-){1}(\d{1,2})(:|\.)?(\d{1,2})?
Here I have an example with most of the use cases I need.
You may add \S* after Etc/ to make sure Etc/ is checked even if there are any zero or more non-whitespace chars between Etc/ and the expected match:
(?<!\bEtc/\S*)((UTC|GMT)?([+-])(\d{1,2})[:.]?(\d{1,2})?)
See the .NET regex demo
Details:
(?<!\bEtc/\S*) - a negative lookbehind that matches a location that is not immediately preceded with a whole word Etc/ and then zero or more non-whitespace chars
(UTC|GMT)? - an optional substring, UTC or GMT
([+-]) - + or -
(\d{1,2}) - one or two digits
[:.]? - an optional : or .
(\d{1,2})? - an optional sequence of one or two digits (equal to (\d{0,2})).
As you are already capturing all data in groups, another way could be getting all the matches of Etc/ out of the way, and use your pattern to capture what you want in the groups.
Note that you can change groupings of single chars like (:|\.) to a character class ([:.])
\bEtc/\S*|(UTC|GMT)?([+-])(\d{1,2})([:.])?(\d{1,2})?
\bEtc/\S* Match Etc/ and optional non whitespace chars
| Or
(UTC|GMT)?([+-])(\d{1,2})([:.])?(\d{1,2})? Your pattern with all the separate groups.
Regex demo
Or with just a single group:
\bEtc/\S*|((?:GMT|UTC)?\+\d{2}(?:[:.]\d{2})?)
Regex demo

Regex to match pattern consisting of several groups

I have the following regular expression, but it only matches the last occurrence of the pattern found. The regular expression is designed to match the following pattern:
A single digit followed by a \
A word followed by \
Another word followed by \
The forth group can either be a single word followed by a \ or 2 or 3 words followed by \
The fifth group must be a floating point number in the format 00.00
The regular expression is:
([0-9])\\(\w+)\\(\w+)\\((\w+\s+\w+\s+\w+)|\w+\s\w+|\w+)\\([+-]?\d*\.\d+)(?![-+0-9\\.])\\
The string being match is:
2\James\Brown\Football Club Mu\15.45\1\Jessie\Ellis\Football Club Performance\15.48\4\Dane\Brown\FC Football \15.52\5\Richardo\Flemmings\Football Club Striders\15.53\7\Lawrence\Brown\Football Club Testing\15.53\8\Jermy\Black\Football Club Ch\15.34\\
The match of the last record is only detected if the regex expression does not terminate with \\ and the string that is to be matched against the regular expression does not terminate with "\\".
Note, the string that is to be compared to the regular expression always terminates with a "\\".
The regex you provided doesn't appear to work at all. I can't make out what you're trying to do with that, especially the '+' and '-' characters. To perfectly match your definition, I've got this:
([0-9])\\\w+\\\w+\\(\w+( \w+)?( \w+)?)\\[0-9][0-9]\.[0-9][0-9]
Although your examples don't quite match your definition, as they have a trailing '\', and the third example has a trailing space in the fourth group. Assuming those examples are valid, I've modified it to this:
([0-9])\\\w+\\\w+\\(\w+( \w+)?( \w+)?) ?\\[0-9][0-9]\.[0-9][0-9]\\

Regular Expression that matches on values after a pipe in between brackets

I'm still learning a lot about regex, so please forgive any naivety.
I've been using this site to test:
http://www.systemtextregularexpressions.com/regex.match
Basically, I'm having issues writing a regular expression that will match on any value after a pipe in between brackets.
Given an example string of:
"<div> \n [dont1.dont2|match1|match2] |dont3 [dont4] dont5. \n </div>"
Expected output would be a collection:
match1,
match2
The closest I've been able to get so far is:
(?!\[.*(\|)\])(?:\|)([\w-_.,:']*)
Above gives me the values, including the pipes, and dont3.
I've also tried this guy:
\|(.*(?=\]))
but it outputs:
|match1|match2
Here's one way of doing it:
(?<=\[[^\]]*\|)[^\]|]*
Here's the meaning of the pattern:
(?<=\[[^\]]*\|) - Lookbehind expression to ensure that any match must be preceded by an open bracket, followed by any number of non-close-bracket characters, followed by a pipe character
(?<= ... ) - Declares a lookbehind expression. Something matching the lookbehind must immediately precede the text in order for it the match. However, the part matched by the lookbehind is not included in the resulting match.
\[ - Matches an open bracket character
[^\]]* - Matches any number of non-close-bracket characters
\| - Matches a pipe character
[^\]|]* - Matches any number of characters which are neither close brackets nor pipe characters.
The lookbehind is greedy, so it will allow for any number of pipes between the open bracket and the matching text.
try this:
\[.*?(?:\|(?<mydata>.*?))+\]
note: the online tool will only show you the last capture inside a quantifed () for a given match, but .NET will remember each capture of a group that matches multiple times
Try this:
^<div>\s*[^|]+|([^|]+)|([^|]+)

Need value in regex.match group

I want to match regex such that the sign(+ or -) in one group and figure in other group. It may possible that figure comes without any sign(+ or -)
Example
[-] 87.90
[+] 87.78
(-) 87.90
(+) 87.78
89
-89.56
- 89.98
I have used below regular expression
^\W*(\-|\+|)\W*(\d+(\.\d+)?)
By this I am getting empty in group 1
If I use
^\W*(\-|\+)\W*(\d+(\.\d+)?)
then 3rd figure will not match. So in short I want to match figure with (+ or -) or without any sign.
Group 1 is empty because the \W* greedily matches all non-word characters, that is, all parentheses and signs.
You should specify the literal parentheses in the pattern and a character class will be a more natural construct to match either a + or a -:
(?:\(?([-+])\)?)?\p{Zs}*(\d+(\.\d+)?)
See regex demo (if you need a full string match, use ^ at the start and $ at the end of the pattern).
Regex matches:
(?:\(?([-+])\)?)? - an optional non-capturing group ((?:...)) that matches a ( optionally, followed by a plus or minus (Group 1), and then by an optional )
\p{Zs}* - zero or more whitespace symbols
(\d+(\.\d+)?) - (Group 2) one or more digits followed by an optional capturing group (Group 3) that matches a period followed by one or more digits.
Result:

Problem with regex, how do I get all with \S up until a special character?

Ive got the text:
192.168.20.31 Url=/flash/56553550_hi.mp4?token=(uniquePlayerReference=81781956||videoId=1)
And im trying to get the uniquePlayerReference and the videoId
Ive tried this regular expression:
(?<=uniquePlayerReference=)\S*
but it matches:
81781956||videoId=1)
And then I try and get the video id with this:
(?<=videoId=)\S*
But it matches the ) after the videoId.
My question is two fold:
1) How do I use the \S character and get it to stop at a character? (essentially what is the regex to do what i want) I cant get it to stop at a defined character, I think I need to use a positive lookahead to match but not include the double pipe).
2) When should I use brackets?
The problem is the mul;tiplicity operator you have here - the * - which means "as many as possible". If you have an explicit number in mind you can use the operator {a,b} where a is a minimum and b a maximum number fo matches, but if you have an unknown number, you can't use \S (which is too generic).
As for brackets, if you mean () you use them to capture a part of a match for backreferencing. Bit complicated, think you need to use a reference for that.
I think you want something like this:
/uniquePlayerReference=(\d+)||videoId=(\d+)/i
and then backreference to \1 and \2 respectively.
Given that both id's are numeric you are probably better off using \d instead of \S. \d only matches numeric digits whereas \S matches any non-whitespace character.
What you might also do is a non gready match up till the character you do not want to match like so:
uniquePlayerReference=(.*?)\|\|videoId=(.*?)\)
Note that I have escaped both the | and ) characters because otherwise they would have a special meaning inside a regex.
In C# you would use this like so: (which also answers your question what the brackets are for, they are meant to capture parts of the matched result).
Regex regex = new Regex(#"uniquePlayerReference=(.*?)\|\|videoId=(.*?)\)");
Match match = regex.Match(
"192.168.20.31 Url=/flash/56553550_hi.mp4?token=(uniquePlayerReference=81781956||videoId=1)");
if (match.Success)
{
string playerReference = match.Groups[1].Value;
string videoId = match.Groups[2].Value;
// Etc.
}
If the ID isn't just digits then you could use [^|] instead of \S, i.e.
(?<=uniquePlayerReference=)[^|]*
Then you can use
(?<=videoId=)[^)]*
For the video ID
The \S means it matches any non-whitespace character, including the closing parenthesis. So if you had to use \S, you would have to explicitly say stop at the closing parenthesis, like this:
videoId=(\S+)\)
Therefore, you are better off using the \d, since what you are looking for are numeric:
uniquePlayerReference=(\d+)
videoId=(\d+)

Categories