Regex containing two specific characters - c#

I have the following regex, which is not working:
#"^[a-z]{1}[a-z0-9\-_(%i)]*$"
The user is allowed to use %i, but only in this combination. Only % is not allowed. The expression in parentheses does not work.
The user input could be for example:
testing123%i
testing123
testing-%i-123
But this is not allowed:
testing%123

A character class only matches 1 single char. You need to take %i out of the character class if you want to match %i as a sequence:
^[a-z](?:[a-z0-9_-]|%i)*$
See the regex demo
Details:
^ - start of a string
[a-z] - a lowervase ASCII letter
(?:[a-z0-9_-]|%i)* - zero or more occurrences of:
[a-z0-9_-] - a lowercase ASCII letter, a digit, _ or -
| - or
%i - a literal char sequence %i
$ - end of string.

string pattern = #"\b(?!(?:.\B)(.)(?:\B.)\1)[%i]+\b";
string input = "testing123%i";
if (Regex.IsMatch(input, pattern))
{
return true;
}

Related

Building a regular expression in C#

How to check the following text in C# with Regex:
key_in-get { 43243225543543543 };
or
key_in_set { password123 : 34980430943834 };
I tried to build a regular expression, but I failed after few hours.
Here is my code:
string text1 = "key_in-get { 322389238237 };";
string text2 = "key_in-set { password123 : 322389238237 };";
string pattern = "key_in-(get|set) { .* };";
var result1 = Regex.IsMatch(text, pattern);
Console.Write("Is valid: {0} ", result1);
var result2 = Regex.IsMatch(text, pattern);
Console.Write("Is valid: {0} ", result2);
I have to check if there is "set" or "get".
If the pattern finds "set" then it can only accept following pattern "text123 : 123456789", and if it finds "get" then should accept only "123456789".
You can use
key_in-(?:get|(set)) {(?(1) \w+ :) \w+ };
key_in-(?:get|(set))\s*{(?(1)\s*\w+\s*:)\s*\w+\s*};
key_in-(?:get|(set))\s*{(?(1)\s*\w+\s*:)\s*\d+\s*};
See the regex demo. The second one allows any amount of any whitespace between the elements and the third one allows only digits after : or as part of the get expression.
If the whole string must match, add ^ at the start and $ at the end of the pattern.
Details:
key_in- - a substring
(?:get|(set)) - get or set (the latter is captured into Group 1)
\s* - zero or more whitespaces
{ - a { char
(?(1)\s*\w+\s*:) - a conditional construct: if Group 1 matched, match one or more word chars enclosed with zero or more whitespaces and then a colon
\s*\w+\s* - one or more word chars enclosed with zero or more whitespaces
}; - a literal substring.
In the pattern that you tried key_in-(get|set) { .* }; you are matching either get or set followed by { until the last occurrence of } which could possibly also match key_in-get { }; };
As an alternative solution, you could use an alternation | specifying each of the accepted parts for the get and the set.
key_in-(?:get\s*{\s*\w+|set\s*{\s*\w+\s*:\s*\w+)\s*};
The pattern matches
key_in- Match literally
(?: Non capture group
get\s*{\s*\w+ Match get, { between optional whitespace chars and 1+ word chars
| Or
set\s*{\s*\w+\s*:\s*\w+ Match set, { between optional whitespace chars and word chars on either side with : in between.
) Close non capture group
\s*}; Match optional whitespace chars and };
Regex demo

Regex to match positive and negative numbers and text between "" after a character

I need a regex for an input that contains positive and negative numbers and sometimes a string between " and ". I'm not sure if this can be done in only one pattern. Here's some test cases for the pattern:
*PATH "C:\Users\User\Desktop\Media\SoundBanks\Ambient\WAV_Data\AD_SMP_SFX_WIND0.wav"
*NODECOLOR 0 255 140
*FILEREF -7
*FREQUENCY 22050
The idea would be to use a pattern that returns:
C:\Users\User\Desktop\Media\SoundBanks\Ambient\WAV_Data\AD_SMP_SFX_WIND0.wav
0 255 140
-7
22050
The content always goes after the character *. I've split this in two patterns because I don't know how to do it all in one, but doesn't work:
MatchCollection NumberMtaches = Regex.Matches(FileLine, #"(?<=[*])-?[0-9]+");
MatchCollection FilePathMatches = Regex.Matches(FileLine, #"/,([^,]*)(?=,)/g");
You may read the file into a string and run the following regex:
var matches = Regex.Matches(filecontents, #"(?m)^\*\w+[\s-[\r\n]]*""?(.*?)""?\r?$")
.Cast<Match>()
.Select(x => x.Groups[1].Value)
.ToList();
See the .NET regex demo.
Details:
(?m) - RegexOptions.Multiline option on
^ - start of a line
\* - a * char
\w+ - one or more word chars
[\s-[\r\n]]* - zero or more whitespaces other than CR and LF
"? - an optional " char
(.*?) - Group 1: any zero or more chars other than an LF char, as few as possible
"? - an optional " char
\r? - an optional CR
$ - end of a line/string.

Match only the nth occurrence using a regular expression

I have a string with 3 dates in it like this:
XXXXX_20160207_20180208_XXXXXXX_20190408T160742_xxxxx
I want to select the 2nd date in the string, the 20180208 one.
Is there away to do this purely in the regex, with have to resort to pulling out the 2 match in code. I'm using C# if that matters.
Thanks for any help.
You could use
^(?:[^_]+_){2}(\d+)
And take the first group, see a demo on regex101.com.
Broken down, this says
^ # start of the string
(?:[^_]+_){2} # not _ + _, twice
(\d+) # capture digits
C# demo:
var pattern = #"^(?:[^_]+_){2}(\d+)";
var text = "XXXXX_20160207_20180208_XXXXXXX_20190408T160742_xxxxx";
var result = Regex.Match(text, pattern)?.Groups[1].Value;
Console.WriteLine(result); // => 20180208
Try this one
MatchCollection matches = Regex.Matches(sInputLine, #"\d{8}");
string sSecond = matches[1].ToString();
You could use the regular expression
^(?:.*?\d{8}_){1}.*?(\d{8})
to save the 2nd date to capture group 1.
Demo
Naturally, for n > 2, replace {1} with {n-1} to obtain the nth date. To obtain the 1st date use
^(?:.*?\d{8}_){0}.*?(\d{8})
Demo
The C#'s regex engine performs the following operations.
^ # match the beginning of a line
(?: # begin a non-capture group
.*? # match 0+ chars lazily
\d{8} # match 8 digits
_ # match '_'
) # end non-capture group
{n} # execute non-capture group n (n >= 0) times
.*? # match 0+ chars lazily
(\d{8}) # match 8 digits in capture group 1
The important thing to note is that the first instance of .*?, followed by \d{8}, because it is lazy, will gobble up as many characters as it can until the next 8 characters are digits (and are not preceded or followed by a digit. For example, in the string
_1234abcd_efghi_123456789_12345678_ABC
capture group 1 in (.*?)_\d{8}_ will contain "_1234abcd_efghi_123456789".
You can use System.Text.RegularExpressions.Regex
See the following example
Regex regex = new Regex(#"^(?:[^_]+_){2}(\d+)"); //Expression from Jan's answer just showing how to use C# to achieve your goal
GroupCollection groups = regex.Match("XXXXX_20160207_20180208_XXXXXXX_20190408T160742_xxxxx").Groups;
if (groups.Count > 1)
{
Console.WriteLine(groups[1].Value);
}

How to write the regex pattern to get the matched string?

Am struggling in writing the regular expression pattern for the below string. I used the below pattern to get the matched string. But, i got the error.
Note: The input string may be anyone of the below input string.
string input = "IN-7874 - hello";
// or "IN-7874 - Hello"
// "IN-7874 - 1) hello"
// "IN-7874 - 1. hello"
// "IN-7874 - 1)hello"
// "IN-7874 - 1.hello"
string pattern = #"^[A-Z]+\\-^[0-9]\s+\\-\\s+^[A-Z]"; //[any number of capital letters]hyphen[any number of numbers(0-9)]space[hyphen]space[numbers or strings]
var a = Regex.Match(input, pattern);
Could anyone please help me on this?
My output should be in the pattern form of [any number of capital letters]hyphen[any number of numbers(0-9)]space[hyphen]space
Example: {SAM-123 - }// don't consider the curly brace.
You can use
^[A-Z]+-[0-9]+\s+-\s+(?:[0-9]+[.)]\s*)?[A-Za-z]+
See the regex demo
Explanation:
^ - start of string
[A-Z]+ - 1 or more uppercase ASCII letters
- - a hyphen
[0-9]+ - 1 or more digits
\s+ - 1+ whitespaces
- - a hyphen
\s+ - see above
(?:[0-9]+[.)]\s*)? - an optional sequence of:
[0-9]+ - 1+ digits
[.)] - a literal . or )
\s* - 0+ whitespaces
[A-Za-z]+ - 1 or more ASCII letters

How to change regex to handle _ symbol after a number?

I want to have a regex that can match the following names:
Standard_DS1_v2
Standard_DS2_v2
...
Standard_DS15_v2
Standard_DS1
Standard_DS2
...
Standard_DS14
Standard_GS1
Standard_GS2
...
Standard_GS5
Now I have the following regex:
private const string PremiumStorageRoleSizesRegex = #"^Standard_((DS)|(GS))\d+$";
machineSizeMetadatas = machineSizeMetadatas.Where(metadata => Regex.IsMatch(metadata.Name, PremiumStorageRoleSizesRegex));
But I don't know how to handle the first sequence (Standard_DS1_v2).
How can I change my regex?
You may use this regex with an optional group:
^Standard_(DS|GS)\d+(?:_v\d+)?$
^^^^^^^^^^
Or a simpler ^Standard_[DG]S\d+(?:_v\d+)?$ to avoid alternation group. See the regex demo
You may add a capturing group wherever you need.
Pattern details:
^ - start of string
Standard_ - a literal Standard_ substring
(DS|GS) - either a DS or GS string (you may replace it with [DG]S)
\d+ - 1 or more digits
(?:_v\d+)? - 1 or 0 (=optional) sequences of _ + v + `1 or more digits
$ - end of string.

Categories