REGEX help needed in c# - c#

I am very new to reg-ex and i am not sure whats going on with this one.... however my friend gave me this to solve my issue BUT somehow it is not working....
string: department_name:womens AND item_type_keyword:base-layer-underwear
reg-ex: (department_name:([\\w-]+))?(item_type_keyword:([\\w-]+))?
desired output: array OR group
1st element should be: department_name:womens
2nd should be: womens
3rd: item_type_keyword:base-layer-underwear
4th: base-layer-underwear
strings can contain department_name OR item_type_keyword, BUT not mendatory, in any order
C# Code
Regex regex = new Regex(#"(department_name:([\w-]+))?(item_type_keyword:([\w-]+))?");
Match match = regex.Match(query);
if (match.Success)
if (!String.IsNullOrEmpty(match.Groups[4].ToString()))
d1.ItemType = match.Groups[4].ToString();
this C# code only returns string array with 3 element
1: department_name:womens
2: department_name:womens
3: womens
somehow it is duplicating 1st and 2nd element, i dont know why. BUT its not return the other elements that i expect..
can someone help me please...
when i am testing the regex online, it looks fine to me...
http://fiddle.re/crvw1
Thanks

You can use something like this to get the output you have in your question:
string txt = "department_name:womens AND item_type_keyword:base-layer-underwear";
var reg = new Regex(#"(?:department_name|item_type_keyword):([\w-]+)", RegexOptions.IgnoreCase);
var ms = reg.Matches(txt);
ArrayList results = new ArrayList();
foreach (Match match in ms)
{
results.Add(match.Groups[0].Value);
results.Add(match.Groups[1].Value);
}
// results is your final array containing all results
foreach (string elem in results)
{
Console.WriteLine(elem);
}
Prints:
department_name:womens
womens
item_type_keyword:base-layer-underwear
base-layer-underwear
match.Groups[0].Value gives the part that matched the pattern, while match.Groups[1].Value will give the part captured in the pattern.
In your first expression, you have 2 capture groups; hence why you have twice department_name:womens appearing.
Once you get the different elements, you should be able to put them in an array/list for further processing. (Added this part in edit)
The loop then allows you to iterate over each of the matches, which you cannot exactly do with if and .Match() (which is better suited for a single match, while here I'm enabling multiple matches so the order they are matched doesn't matter, or the number of matches).
ideone demo
(?:
department_name # Match department_name
| # Or
item_type_keyword # Match item_type_keyword
)
:
([\w-]+) # Capture \w and - characters

It's better to use the alternation (or logical OR) operator | because we don't know the order of the input string.
(department_name:([\w-]+))|(item_type_keyword:([\w-]+))
DEMO
String input = #"department_name:womens AND item_type_keyword:base-layer-underwear";
Regex rgx = new Regex(#"(?:(department_name:([\w-]+))|(item_type_keyword:([\w-]+)))");
foreach (Match m in rgx.Matches(input))
{
Console.WriteLine(m.Groups[1].Value);
Console.WriteLine(m.Groups[2].Value);
Console.WriteLine(m.Groups[3].Value);
Console.WriteLine(m.Groups[4].Value);
}
IDEONE

Another idea using a lookahead for capturing and getting all groups in one match:
^(?!$)(?=.*(department_name:([\w-]+))|)(?=.*(item_type_keyword:([\w-]+))|)
as a .NET String
"^(?!$)(?=.*(department_name:([\\w-]+))|)(?=.*(item_type_keyword:([\\w-]+))|)"
test at regexplanet (click on .NET); test at regex101.com
(add m multiline modifier if multiline input: "^(?m)...)

If you use any spliting with And Or , etc that you can use
(department_name:(.*?)) AND (item_type_keyword:(.*?)$)
•1: department_name:womens
•2: womens
•3: item_type_keyword:base-layer-underwear
•4: base-layer-underwear

(?=(department_name:\w+)).*?:([\w-]+)|(?=(item_type_keyword:.*)$).*?:([\w-]+)
Try this.This uses a lookahead to capture then backtrack and again capture.See demo.
http://regex101.com/r/lS5tT3/52

Related

Regex match with multiple delimiters

I have a regex that takes out all parts of a string in between citation marks.
\(([^)]*)\)
So
*- (Hello) + (World) -
returns two matches
(Hello)
(World)
Im trying but failing to modify it so that i also get the parts in between as their own matches. Like:
*-
(Hello)
+
(World)
-
Is it even possible?
In this case, with the current regex, you may use Regex.Split with the pattern wrapped in a capturing group:
var tokens = Regex.Split(s, #"(\([^)]*\))");
Or even, when matches occur in the leading/trailing positions:
var tokens = Regex.Split(s, #"(\([^)]*\))").Where(m => !string.IsNullOrEmpty(m));
See the regex demo:
Note you may need to replace all capturing groups in your regex into non-capturing to use this feature. When you use "technical" capturing groups to later refer to using backreferences, you would have to build the non-matching substring array using multiple matching and calling .Substring() on the input using the information on the match position.
You could use an alternation to match either the parenthesis with the characters \([^)]*\) or | match one or more times the characters listed in a character class [*+-]+
\([^)]*\)|[*+-]+
string pattern = #"\([^)]*\)|[*+-]+";
string input = #"*- (Hello) + (World) - ";
foreach (Match m in Regex.Matches(input, pattern))
{
Console.WriteLine(m.Value);
}
That would give you:
*-
(Hello)
+
(World)
-
Demo C#

RegEx ignoring part of string to extract out text

I have the following string:
#delimabc#delim#delim123#delim#delim456#delim
and I need to write a .Net RegEx that finds 3 matches in this example (but assume the number of matches will be variable:
abc
123
456
How can I write a RegEx so that the expression only matches the first and second #delim, and then the third and fourth and so on?
The following will of course capture from the first to the last instance of the #delim string.
#delim(.+)+#delim
You could use look behind like:
(?<=#delim)\w+
(?<=#delim) is using a Positive Lookbehind which will match the characters #delim literally (case sensitive)
while \w+ will match any word character from [a-zA-Z0-9_]. To include or exclude characters you could replace \w by [a-zA-Z0-9_] and include the new characters or remove those that should not be evaluated in your expression.
Online Demo
Here is .NET Online Demo:
.NET Online Demo
VB.NET version
Dim sampleInput="#delimabc#delim#delim123#delim#delim456#delim"
Dim results = Regex.Matches(sampleInput,"(?<=#delim)\w+")
For Each item As Group In results
Console.WriteLine("Line: {0}", item)
Next
C# Version
var sampleInput = "#delimabc#delim#delim123#delim#delim456#delim";
var results = Regex.Matches(sampleInput, "(?<=#delim)\\w+");
foreach (Group item in results) {
Console.WriteLine("Line: {0}", item);
}
Updated version:
(?<=#delim)[^#].+?(?=#delim|$)
#delim(.+?)#delim
Try this .Set g flag.Just modifed your regex to add ?.Grab the caotures.See demo.
http://regex101.com/r/uH3tP3/1
You can use split on this regex:
(?:#delim)+
RegEx Demo
Alternatively replace given regex pattern by an empty string.

C# RegEx - get only first match in string

I've got an input string that looks like this:
level=<device[195].level>&name=<device[195].name>
I want to create a RegEx that will parse out each of the <device> tags, for example, I'd expect two items to be matched from my input string: <device[195].level> and <device[195].name>.
So far I've had some luck with this pattern and code, but it always finds both of the device tags as a single match:
var pattern = "<device\\[[0-9]*\\]\\.\\S*>";
Regex rgx = new Regex(pattern);
var matches = rgx.Matches(httpData);
The result is that matches will contain a single result with the value <device[195].level>&name=<device[195].name>
I'm guessing there must be a way to 'terminate' the pattern, but I'm not sure what it is.
Use non-greedy quantifiers:
<device\[\d+\]\.\S+?>
Also, use verbatim strings for escaping regexes, it makes them much more readable:
var pattern = #"<device\[\d+\]\.\S+?>";
As a side note, I guess in your case using \w instead of \S would be more in line with what you intended, but I left the \S because I can't know that.
depends how much of the structure of the angle blocks you need to match, but you can do
"\\<device.+?\\>"
I want to create a RegEx that will parse out each of the <device> tags
I'd expect two items to be matched from my input string:
1. <device[195].level>
2. <device[195].name>
This should work. Get the matched group from index 1
(<device[^>]*>)
Live demo
String literals for use in programs:
#"(<device[^>]*>)"
Change your repetition operator and use \w instead of \S
var pattern = #"<device\[[0-9]+\]\.\w+>";
String s = #"level=<device[195].level>&name=<device[195].name>";
foreach (Match m in Regex.Matches(s, #"<device\[[0-9]+\]\.\w+>"))
Console.WriteLine(m.Value);
Output
<device[195].level>
<device[195].name>
Use named match groups and create a linq entity projection. There will be two matches, thus separating the individual items:
string data = "level=<device[195].level>&name=<device[195].name>";
string pattern = #"
(?<variable>[^=]+) # get the variable name
(?:=<device\[) # static '=<device'
(?<index>[^\]]+) # device number index
(?:]\.) # static ].
(?<sub>[^>]+) # Get the sub command
(?:>&?) # Match but don't capture the > and possible &
";
// Ignore pattern whitespace is to document the pattern, does not affect processing.
var items = Regex.Matches(data, pattern, RegexOptions.IgnorePatternWhitespace)
.OfType<Match>()
.Select (mt => new
{
Variable = mt.Groups["variable"].Value,
Index = mt.Groups["index"].Value,
Sub = mt.Groups["sub"].Value
})
.ToList();
items.ForEach(itm => Console.WriteLine ("{0}:{1}:{2}", itm.Variable, itm.Index, itm.Sub));
/* Output
level:195:level
name:195:name
*/

Select only numeric part of a selection in a single regex

Well, I don't know how to explain that exactly, but I have this text:
abc=0;def=2;abc=1;ghi=4;jkl=2
The thing I want to do is select abc=0 and abc=1 but excluding abc part...
My regex is: abc=\d+, but it includes abc part...
I readed something about this, and the answer was this: (?!abc=)\d+ but It select all the numbers inside the text...
So, can somebody help me with this?
Thanks in advance.
If your language supports \K then you could use the below regex to matche the number which was just after to the string abc=,
abc=\K\d+
DEMO
OR
use a positive look-behind if your language didn't support \K,
(?<=abc=)\d+
DEMO
C# code would be,
{
string str = "abc=0;def=2;abc=1;ghi=4;jkl=2";
Regex rgx = new Regex(#"(?<=abc=)\d+");
foreach (Match m in rgx.Matches(str))
Console.WriteLine(m.Value);
}
IDEONE
Explanation:
(?<=abc=) Positive lookbehind which actually sets the matching marker just after to the string abc=.
\d+ Matches one or more digits.
You don't need a lookaround assertion here. You can simply use a capturing group to capture the matched context that you want and refer back to the matched group using the Match.Groups Property.
abc=(\d+)
Example:
string s = "abc=0;def=2;abc=1;ghi=4;jkl=2";
foreach (Match m in Regex.Matches(s, #"abc=(\d+)"))
Console.WriteLine(m.Groups[1].Value);
Output
0
1

Regular Expression Groups in C#

I've inherited a code block that contains the following regex and I'm trying to understand how it's getting its results.
var pattern = #"\[(.*?)\]";
var matches = Regex.Matches(user, pattern);
if (matches.Count > 0 && matches[0].Groups.Count > 1)
...
For the input user == "Josh Smith [jsmith]":
matches.Count == 1
matches[0].Value == "[jsmith]"
... which I understand. But then:
matches[0].Groups.Count == 2
matches[0].Groups[0].Value == "[jsmith]"
matches[0].Groups[1].Value == "jsmith" <=== how?
Looking at this question from what I understand the Groups collection stores the entire match as well as the previous match. But, doesn't the regexp above match only for [open square bracket] [text] [close square bracket] so why would "jsmith" match?
Also, is it always the case the the groups collection will store exactly 2 groups: the entire match and the last match?
match.Groups[0] is always the same as match.Value, which is the entire match.
match.Groups[1] is the first capturing group in your regular expression.
Consider this example:
var pattern = #"\[(.*?)\](.*)";
var match = Regex.Match("ignored [john] John Johnson", pattern);
In this case,
match.Value is "[john] John Johnson"
match.Groups[0] is always the same as match.Value, "[john] John Johnson".
match.Groups[1] is the group of captures from the (.*?).
match.Groups[2] is the group of captures from the (.*).
match.Groups[1].Captures is yet another dimension.
Consider another example:
var pattern = #"(\[.*?\])+";
var match = Regex.Match("[john][johnny]", pattern);
Note that we are looking for one or more bracketed names in a row. You need to be able to get each name separately. Enter Captures!
match.Groups[0] is always the same as match.Value, "[john][johnny]".
match.Groups[1] is the group of captures from the (\[.*?\])+. The same as match.Value in this case.
match.Groups[1].Captures[0] is the same as match.Groups[1].Value
match.Groups[1].Captures[1] is [john]
match.Groups[1].Captures[2] is [johnny]
The ( ) acts as a capture group. So the matches array has all of matches that C# finds in your string and the sub array has the values of the capture groups inside of those matches. If you didn't want that extra level of capture jut remove the ( ).
Groups[0] is your entire input string.
Groups[1] is your group captured by parentheses (.*?). You can configure Regex to capture Explicit groups only (there is an option for that when you create a regex), or use (?:.*?) to create a non-capturing group.
The parenthesis is identifying a group as well, so match 1 is the entire match, and match 2 are the contents of what was found between the square brackets.
How? The answer is here
(.*?)
That is a subgroup of #"[(.*?)];

Categories