I keep getting .success as false - c#

I have to read an excel file and check if its name follows a certain pattern.
The pattern is CDFSDDRCxxxCurryymmdd, where xxx is a number, Curr is either EUR or GBP and yymmdd is a date.
This is my file's name, CDFSDDRC603EUR120124.xls. Can also be .xlsx.
And this is my code.
Match nameIsValid = Regex.Match(activeWorkbook.Name,
#"CDFSDDRC(?<xxx>[0-9]+)(?<xxx>[A-Z]+)(?<yymmdd>[0-9][0-9][0|1][0-9][0-3][0-9])\.xls?");
I keep getting nameIsValid.success as false.
I think my Regex expression is ok, but then again.
Any ideas?
Rui Martins

Your pattern for the date matching is somewhat messed up. It doesn't really match dates but just a weir combination of numbers. Also, you can't use | inside character classes. Think closely about how dates are constructed.
Furthermore, you have a duplicate matching group called xxx. This will surely mess up C#'s behaviour when accessing one of them.
Try this one
/CDFSDDRC(?<xxx>\d+)(?<curr>[A-Z]+)(?<yymmdd>\d{2}(?:0[1-9]|1[12])(?:(?:0|1|2)[1-9]|3[0-2]))\.xlsx?/

CDFSDDRC(?<xxx>\d+)(?<curr>EUR|GBP)(?<yymmdd>\d{2}[0-1]\d[0-3]\d)\.xlsx?
The following works for me for both xls and xslx.

Related

Regular Expression for Digits and Special Characters - C#

I use Html-Agility-Pack to extract information from some websites. In the process I get data in the form of string and I use that data in my program.
Sometimes the data I get includes multiple details in the single string. As the name of this Movie "Dog Eats Dog (2012) (2012)". The name should have been "Dog Eats Dog (2012)" rather than the first one.
Above is the one example from many. In order to correct the issue I tried to use string.Distinct() method but it would remove all the duplicate characters in the string as in above example it would return "Dog Eats (2012)". Now it solved my initial problem by removing the 2nd (2012) but created a new one by changing the actual title.
I thought my problem could be solved with Regex but I have no idea as to how I can use it here. As far as I know if I use Regex it would tell me that there are duplicate items in the string according to the defined Regex code.
But how do I remove it? There can be a string like "Meme 2013 (2013) (2013)".
Now the actual title is "Meme 2013" with year (2013) and the duplicate year (2013). Even if I get a bool value indicating that the string has duplicate year, I cant think of any method to actually remove the duplicate substring.
The duplicate year always comes in the end of the string. So what should be the Regex that I would use to determine that the string actually has two years in it, like (2012) (2012)?
If I can correctly identify the string contains duplicate maybe I can use string.LastIndexOf() to try and remove the duplicate part. If there is any better way to do it please let me know.
Thanks.
The right regex is "( \(\d{4}\))\1+".
string pattern = #"( \(\d{4}\))\1+";
new Regex(pattern).Replace(s, "$1");
Example here : https://repl.it/Evcy/2
Explanation:
Capture one " (dddd)" block, and remove all following identical ones.
( \(\d{4}\)) does the capture, \1+ finds any non empty sequence of that captured block
Finally, replace the initial block and its copies by the initial block alone.
This regex will allow for any pattern of whitespace, even none, as in (2013)(2013)
`#"(\(\d{4}\))(?:\s*\1)+"`
I have a demo of it here

regex to replace last two digits of an assemblyversion

I'm working with teamcity and a C# project, and I want to use the file content patcher to replace the last two digits in an assemblyversion (eg: the two stars in [assembly: AssemblyVersion("1.0.*.*")]). I've found the docs on the file content patcher and it suggests using
(^\s*\[\s*assembly\s*:\s*((System\s*\.)?\s*Reflection\s*\.)?\s*AssemblyVersion(Attribute)?\s*\(\s*#?\")(([0-9\*]+\.)+)[0-9\*]+(\"\s*\)\s*\]) if you just want to change the LAST digit, which got me partway there.
I figured if I did (^\s*\[\s*assembly\s*:\s*((System\s*\.)?\s*Reflection\s*\.)?\s*AssemblyVersion(Attribute)?\s*\(\s*#?\")(([0-9\*]+(\.))+)[0-9\*]+(\"\s*\)\s*\]) it would capture the last period as it's own group, letting me replace the two stars without a problem. However it looks like the first star is still captured in the group with the 1.0 (so the group becomes 1.0.*.).
What I want is to restrict the first group to capturing the {major}.{minor}. and then have the last period be it's own group so I could do something like: $1$5\%build.number%$7%build.vcs.number%$8 which would give me AssemblyVersion("1.0.{build#}.{vcs#}")]
Generally I can stumble through regex without many problems but I've been working on this for the last few hours and I can't seem to get it correct. Any information on reaching this conclusion would he appreciated.
If you want to keep to the solution you found to replace while also validating, you may use
(^\s*\[\s*assembly\s*:\s*((System\s*\.)?\s*Reflection\s*\.)?‌​\s*AssemblyVersion(A‌​ttribute)?\s*\(\s*#?‌​\")([0-9\*]+\.[0-9\*‌​]+)\.([0-9\*]+\.[0-9‌​\*]+)(\"\s*\)\s*\])
and replace with $1$5.%build.number%.%build.vcs.number%$7.
See the regex demo
I just unrolled the ([0-9\*]+(\.))+ into ([0-9\*]+\.[0-9\*‌​]+)\.([0-9\*]+\.[0-9‌​\*]+), 2 groups (([0-9\*]+\.[0-9\*‌​]+)) separated with a literal dot (\.). I also had to remove the [0-9\*]+ that followed the ([0-9\*]+(\.))+ pattern.
I would first extract 1.0.*.* and then use Version.Parse.
Much smaller regex (and can be shortened more)..
string input = #"[assembly:AssemblyVersion(""1.2.3.4"")]";
var verStr = Regex.Match(input, #"\[.+?\(\""(.+?)\""\)\]").Groups[1].Value;
var version = Version.Parse(verStr);

how to replace the exact word by another in a list?

I have a list like :
george fg
michel fgu
yasser fguh
I would like to replace fg, fgu, and fguh by "fguhCool" I already tried something like this :
foreach (var ignore in NameToPoulate)
{
tempo = ignore.Replace("fg", "fguhCool");
NameToPoulate_t.Add(tempo);
}
But then "fgu" become "fguhCoolu" and "fguh" become "fguhCooluh" is there are a better idea ?
Thanks for your help.
I assume that this is a homework assignment and that you are being tested for the specific algorihm rather than any code that does the job.
This is probably what your teacher has in mind:
Students will realize that the code should check for "fguh" first, then "fgu" then "fg". The order is important because replacing "fg" will, as you have noticed, destroy a "fguh".
This will by some students be implemented as a loop with if-else conditions in them. So that you will not replace a "fg" that is within an already replaced "fguhCool".
But then you will find that the algorithm breaks down if "fg" and "fgu" are both within the same string. You cannot then allow the presence of "fgu" prevent you to check for "fg" at a different part of the string.
The answer that your teacher is looking for is probably that you should first locate "fguh", "fgu" and "fg" (in that order) and replace them with an intermediary string that doesn't contain "fg". Then after you have done that, you can search for that intermediary string and replace it with "fguhCool".
You could use regular expressions:
Regex.Replace(#"\bfg\b", "fguhCool");
The \b matches a so-called word boundary which means it matches the beginnnig or end of a word (roughly, but for this purpose enough).
Use a regular expression:
Regex.Replace("fg(uh?)?", "fguhCool");
An alternative would be replacing the long words for the short ones first, then replacing the short for the end value (I'm assuming all words - "fg", "fgu" and "fguh" - would map to the same value "fguhCool", right?)
tempo = ignore
.Replace("fguh", "fg")
.Replace("fgu", "fg")
.Replace("fg", "fguhCool");
Obs.: That assumes those words can appear anywhere in the string. If you're worried about whole words (i.e. cases where those words are not substrings of a bigger word), then see #Joey's answer (in this case, simple substitutions won't do, regexes are really the best option).

Regex between, from the last to specific end

Today my wish is to take text form the string.
This string must be, between last slash and .partX.rar or .rar
First I tried to find edge's end of the word and then the beginning. After I get that two elements I merged them but I got empty results.
String:
http://hosting.xyz/1234/15-game.part4.rar.html
http://hosting.xyz/1234/16-game.rar.html
Regex:
Begin:(([^/]*)$) - start from last /
End:(.*(?=.part[0-9]+.rar|.rar)) stop before .partX.rar or .rar
As you see, if I merge that codes I won't get any result.
What is more, "end" select me only .partX instead of .partX.rar
All what I want is:
15-game.part4.rar and 16-game.rar
What i tried:
(([^/]*)$)(.*(?=.part[0-9]+.rar|.rar))
(([^/]*)$)
(.*(?=.part[0-9]+.rar|.rar))
I tried also
/[a-zA-Z0-9]+
but I do not know how select symbols.. This could be the easiest way. But this select only letters and numbers, not - or _.
If I could select symbols..
You don't really need a regex for this as you can merely split the url on / and then grab the part of the file name that you need. Since you didn't mention a language, here's an implementation in Perl:
use strict;
use warnings;
my $str1="http://hosting.xyz/1234/15-game.part4.rar.html";
my $str2="http://hosting.xyz/1234/16-game.rar.html";
my $file1=(split(/\//,$str1))[-1]; #last element of the resulting array from splitting on slash
my $file2=(split(/\//,$str2))[-1];
foreach($file1,$file2)
{
s/\.html$//; #for each file name, if it ends in ".html", get rid of that ending.
print "$_\n";
}
The output is:
15-game.part4.rar
16-game.rar
Nothing could be simpler! :-)
Use this:
new Regex("^.*\/(.*)\.html$")
You'll find your filename in the first captured group (don't have a c# compiler at hand, so can't give you working sample, but you have a working regex now! :-) )
See a demo here: http://rubular.com/r/UxFNtJenyF
I'm not a C# coder so can't write full code here but I think you'll need support of negative lookahead here like this:
new Regex("/(?!.*/)(.+?)\.html$");
Matched Group # 1 will have your string i.e. "16-game.rar" OR "15-game.part4.rar"
Use two regexes:
start to substitute .*/ with nothing;
then substitute \.html with nothing.
Job done!

Regex match a CSV file

I am trying to create a regex to match a CSV file of records in the form of:
optional value, , ,, again some value; this is already, next record;
Now there is an upper limit of commas (10) separating attributes of each record and unlimited number of ; separating each record. Values might or might not be present. I am unexperienced with regex and my effort is rather futile so far. Please help. If necessary, I will include more details.
EDIT
I want to verify that the file is in the required form and get the number of records in it.
Do you really need to use regular expressions for this? Might be a little bit overkill. I'd just perform one String.Split() to get the records, then another String.Split() on each record to get the values. Also rather easy to get the number of elements etc. then.
If you really want to use Regexps, I'd use two steps again:
/(.*?);/ to get the datasets;
/(.*?)[,;]/ to get the values.
Could probably be done with one regexp as well but I'd consider this overkill (as you'd have to find the sub matches etc. identify their parent record, etc.).
Escaped characters would be another thing but rather similar to do: e.g. /(.*?[^\\]);/
try this
bool isvalid = csv.Split(';')
.Select(c => c.Split(',')
.Count())
.Distinct()
.Count() == 1;
Reminds me to the famous article form Coding Horror: Regular Expressions: Now You Have Two Problems.
FileHelpers saved my day when dealing with CSV or other text format.

Categories

Resources