Regex Replace exclude first and nth character - c#

I am trying to mask a string name with * (asterisks) and exclude both the first and nth (5th) characters.
Example:
UserFirstName -> U****F*******
I managed to exclude the first character with (?!^).:
var regex = new Regex("(?!^).");
var result = regex.Replace(stringUserName, "*");
output:
UserFirstName -> U************
How can I also exclude the character in the 5th position?

You may use
(?!^)(?<!^.{4}).
See the regex demo
Pattern details
(?!^) - (it is equal to (?<!^) lookbehind that you may use instead) a negative lookahead that fails the position at the start of string
(?<!^.{4}) - a negative lookbehind that fails the match if, immediately to the left of the current position, there are any four characters other than a newline char from the start of the string
. - any single char other than a newline char.
C# demo:
string text = "UserFirstName";
int SkipIndex = 5;
string pattern = $#"(?!^)(?<!^.{{{SkipIndex-1}}}).";
Console.WriteLine(Regex.Replace(text, pattern, "*"));
Output: U***F********

Without Regex, extra explanation not required ;)
var text = "UserFirstName";
var skip = new[] { 0, 4 }.ToHashSet();
var masked = text.Select((c, index) => skip.Contains(index) ? c : '*').ToArray();
var output = new String(masked);
Console.WriteLine (output); // U***F********
c# Demo

Related

Regex How to Match 2 fields

How would capture both the filenames inside the quotes, and the numbers following as named captures (Regex / C#)?
Files("fileone.txt", 5969784, "file2.txt", 45345333)
Out of every occurrence in the string, the ability to capture "fileone.txt" and the integer following (a loop cycles each pair)
I am trying to use this https://regex101.com/r/MwMzBo/1 but having issues matching without the '[' and ']'.
Required to be able to loop each filename+size as a pair and moving next.
Any help is appreciated!
UPDATE
string file = "Files(\"fileone.txt\", 5969784, \"file2.txt\", 45345333, \"file2.txt\", 45345333)";
var regex = new Regex(#"(?:\G(?!\A)\s*,\s*|\w+\()(?:""(?<file>.*?)""|'(?<file>.*?)')\s*,\s*(?<number>\d+)");
var match = regex.Match(file);
var names = match.Groups["file"].Captures.Cast<Capture>();
var lengths = match.Groups["number"].Captures.Cast<Capture>();
var filelist = names.Zip(lengths, (f, n) => new { file = f.Value, length = long.Parse(n.Value) }).ToArray();
foreach (var item in filelist)
{
// Only returning 1 pair result, ignoring the rest
}
Reading match.Value to confirm what is being read. Only first pair is being picked up.
while (match.Success)
{
MessageBox.Show(match.Value);
match = match.NextMatch();
}
Now we are getting all results properly. I read, that Regex.Match only returns the first matched result. This explains a lot.
You can use
(?:\G(?!\A)\s*,\s*|\w+\()(?:""(?<file>.*?)""|'(?<file>.*?)')\s*,\s*(?<number>\d+)
See the regex demo
Details:
(?:\G(?!\A)\s*,\s*|\w+\() - end of the previous successful match and a comma enclosed with zero or more whitespaces, or a word and an opening ( char
(?:""(?<file>.*?)""|'(?<file>.*?)') - ", Group "file" capturing any zero or more chars other than a newline char as few as possible and then a ", or a ', Group "file" capturing any zero or more chars other than a newline char as few as possible and then a '
\s*,\s* - a comma enclosed with zero or more whitespaces
(?<number>\d+) - Group "number": one or more digits.
I like doing it in smaller pieces :
string input = "cov('Age', ['5','7','9'])";
string pattern1 = #"\((?'key'[^,]+),\s+\[(?'values'[^\]]+)";
Match match = Regex.Match(input, pattern1);
string key = match.Groups["key"].Value.Trim(new char[] {'\''});
string pattern2 = #"'(?'value'[^']+)'";
string values = match.Groups["values"].Value;
MatchCollection matches = Regex.Matches(values, pattern2);
int[] number = matches.Cast<Match>().Select(x => int.Parse(x.Value.Replace("'",string.Empty))).ToArray();

Regular expression not working in dotnet C# but works in online editors [duplicate]

I want to get a Substring out of a String.
The Substring I want is a sequence of numerical characters.
Input
"abcdefKD-0815xyz42ghijk";
"dag4ah424KD-42ab333k";
"BeverlyHills90210KD-433Nokia3310";
Generally it could be any String, but they all have one thing in common:
There is a part that starts with KD-
and ends with a number
Everything after the number to be gone.
In the examples above this number would be 0815, 42, 433 respectively. But it could be any number
Right now I have a Substring that contains all numerical characters after KD- but I would like to have only the 0815ish part of the string.
What i have so far
String toMakeSub = "abcdef21KD-0815xyz429569468949489694694689ghijk";
toMakeSub = toMakeSub.Substring(toMakeSub.IndexOf("KD-") + "KD-".Length);
String result = Regex.Replace(toMakeSub, "[^0-9]", "");
The Result is 0815429569468949489694694689 but I want only the 0815 (it could be any length though so cutting after four digits is not possible).
Its as easy as the following pattern
(?<=KD-)\d+
The way to read this
(?<=subpattern) : Zero-width positive lookbehind assertion. Continues matching only if subpattern matches on the left.
\d : Matches any decimal digit.
+ : Matches previous element one or more times.
Example
var input = "abcdef21KD-0815xyz429569468949489694694689ghijk";
var regex = new Regex(#"(?<=KD-)\d+");
var match = regex.Match(input);
if (match.Success)
{
Console.WriteLine(match.Value);
}
input = "abcdef21KD-0815xyz429569468949489694694689ghijk, KD-234dsfsdfdsf";
// or to match multiple times
var matches = regex.Matches(input);
foreach (var matchValue in matches)
{
Console.WriteLine(matchValue);
}

Use regular expression in C# to select a specific occurrence from a string by limiting input

Using C#, i am stuck while trying to extract a specific string while limiting the string to be matched. Here is my input string:
NPS_CNTY01_10112018_Adult_Submittal.txt
I would like to extract 01 after CNTY and ingnore anything after 01.
So far i have the regex to be:
(?!NPS_CNTY)\d{2}
But the above regex gets many other digit matches from the input string. One approach i was thinking was to limit the input to 9 characters to eventually get 01. But somehow not able to achieve that. Any help is appreciated.
I would like to add that the only variable data in this input string is:
NPS_CNTY[two digit county code excluding this bracket]_[date in MMDDYYYY format excluding the brackets]_Adult_Submittal.txt.
Also please limit solutions to regex's.
The (?!NPS_CNTY)\d{2} pattern matches a location that is not immediately followed with NPS_CNTY and then matches 2 digits. The lookahead always returns true since two digits cannot start a NPS_CNTY char sequence, it is redundant.
You may use a positive lookbehind like this to get 01:
var m = Regex.Match(s, #"(?<=NPS_CNTY)\d+");
var result = "";
if (m.Success)
{
result = m.Value;
}
See the .NET regex demo
Here, (?<=NPS_CNTY), a positive lookbehind, matches a location that is immediately preceded with NPS_CNTY and then \d+ matches 1 or more digits.
An equivalent solution using capturing mechanism is
var m = Regex.Match(s, #"NPS_CNTY(\d+)");
var result = "";
if (m.Success)
{
result = m.Groups[1].Value;
}
If the string always start with NPS_CNTY and you have to extract 2 digits then you don't need a regular expression. Just use Substring() method:
string text = #"NPS_CNTY01_01141980_Adult_Submittal.txt";
string digits = text.Substring(8, 2);
EDIT:
In case you need to match N digits after NPS_CNTY you can use the following code:
string text = #"NPS_CNTY012_01141980_Adult_Submittal.txt";
string digits = text.Replace("NPS_CNTY", string.Empty)
.Split("_", StringSplitOptions.RemoveEmptyEntries)
.FirstOrDefault();

How can I find a Regex match at a specific location of the string in C#?

I want to find out whether a Regex matches at a specific location of a string.
Example:
Regex r = new Regex("d");
string s = "abcdefg";
I want the match function to find a match only if it is at the exact given location so that using the example above, matching at the locations 1, 3, and 5 should give no match, match, and no match, respectively. Unfortunately the C# Regex.Match method gives:
r.Match(s, 1); // => match ("d")
r.Match(s, 3); // => match ("d")
r.Match(s, 5); // => no match
I understand this is because the Regex.Match method searches forward for the first match, but how do I prevent this behavior without having to make substrings?
Add \G to the beginning of your regex:
Regex r = new Regex(#"\Gd");
string s = "abcdefg";
Console.WriteLine(r.Match(s, 1).Success); // False
Console.WriteLine(r.Match(s, 3).Success); // True
Console.WriteLine(r.Match(s, 5).Success); // False
\G anchors the match to the position where the previous match ended, or to the beginning of the string if there was no previous match. With the second argument to Match, you're effectively telling it there was a previous match, which ended at that location.
Use substring and the start-of-string anchor ^:
Regex r = new Regex("^d"); // Use the start of string anchor
string s = "abcdefg";
r.IsMatch(s.Substring(3)); // Match at exactly fourth character (0-based index 3)
Alternatively, to avoid copying the string in memory, use quantified .:
Regex r = new Regex("^.{3}d");
r.IsMatch("abcdefg");
The pattern ^.{3}d says
Start at the beginning of the string
Match exactly three characters of anything
Then match the letter 'd'
Well, if you're always looking for the same index, you can stuff a little more your regex by adding wildcards at the beginning to "pad" the result, i.e. :
Regex r = new Regex("^.{3}d");
r.isMatch("abcdefg"); // true
r.isMatch("adcffed"); // false
r.isMatch("abcddef"); // true
On the other hand, if you wanna use the same regex with different indexes, you can just use the ^ character to match the beginning of the string only :
Regex r = new Regex("^d");
r.isMatch("abcdefg".substring(3)); // true
r.isMatch("adcffed".substring(3)); // false
r.isMatch("abcddef".substring(1)); // false
NB : if you're just looking for a simple string and not a patter, you should simply use string.IndexOf

Get partial string from string

I have the following string:
This isMyTest testing
I want to get isMyTest as a result. I only have two first characters available("is"). The rest of the word can vary.
Basically, I need to select a first word delimeted by spaces which starts with chk.
I've started with the following:
if (text.contains(" is"))
{
text.LastIndexOf(" is"); //Should give me index.
}
now I cannot find the right bound of the word since I need to match on something like
You can use regular expressions:
string pattern = #"\bis";
string input = "This isMyTest testing";
return Regex.Matches(input, pattern);
You can use IndexOf to get the index of the next space:
int startPosition = text.LastIndexOf(" is");
if (startPosition != -1)
{
int endPosition = text.IndexOf(' ', startPosition + 1); // Find next space
if (endPosition == -1)
endPosition = text.Length - 1; // Select end if this is the last word?
}
What about using a regex match? Generally if you are searching for a pattern in a string (ie starting with a space followed by some other character) regex are perfectly suited to this. Regex statements really only fall apart in contextually sensitive areas (such as HTML) but are perfect for a regular string search.
// First we see the input string.
string input = "/content/alternate-1.aspx";
// Here we call Regex.Match.
Match match = Regex.Match(input, #"[ ]is[A-z0-9]*", RegexOptions.IgnoreCase);
// Here we check the Match instance.
if (match.Success)
{
// Finally, we get the Group value and display it.
string key = match.Groups[1].Value;
Console.WriteLine(key);
}

Categories

Resources