Reputation: 14787
Having trouble determining if a file name conforms to a specific convention as follows. Using regular expression in C# .Net 4.0.
Valid Format: xxxxT_SSS_sss[i]_t#y.png
where
// x = Any single character.
// T = Digit: 1 to 7 inclusive.
// _SSS = Positive Integer: 000 to 999 inclusive. Always padded with leading zeros.
// _sss = Positive Integer: 000 to 999 inclusive. Always padded with leading zeros.
// i = Random text of any length including any characters. Will always be enclosed in square [] brackets. Optional.
// _t = Positive Integer: 0 to 999 inclusive. Not padded. Optional.
// #y = Positive Integer: 0 to 999 inclusive. Not padded. Optional.
UPDATE
Valid file names:
File1_000_000.png
File1_000_000_1.png
File1_000_000#2.png
File1_000_000_1#2.png
File1_000_000[text].png
File1_000_000[text]_1.png
File1_000_000[text]#2.png
File1_000_000[text]_1#2.png
The regex I've been trying is:
^(.{4}\\d_\\d{3}_\\d{3}(\\[\\w\\s]+\\])?(_\\d{1,3})?(\\#\\d{1,3})?)
This returns true for all the sample file names BUT, if I change File1_000_000[text]_1#2.png
to File1_000_000[text]_#2.png
by deleting the digit 1
, it still returns true. The underscore is a part of the _t
.
Upvotes: 3
Views: 364
Reputation: 751
@"^.{4}[2-7](_\d{3}){2}(\[.+\])?(_\d{1,3})?(\#\d{1,3})?\.png$"
Upvotes: 0
Reputation: 13356
This one should work:
^.{4}[2-7]{3}(_[0-9]{3}){2}(\[.+?\])?(_[1-9][0-9]{0,2})?(#[1-9][0-9]{0,2})?\.png$
Upvotes: 0
Reputation: 6136
This unit test will fail because you have specified the pattern must have an integer 2-7 at the 4th character positionm, where as File1
has 1
.
[Test]
public void StackOverflow()
{
Regex pattern = new Regex(@"^.{4}[2-7](_\d{3}){2}(\[[^\]]+\])?(_\d{1,3})?(#\d{1,3})?\.png$");
Assert.IsTrue(pattern.IsMatch("File1_000_000.png"));
Assert.IsTrue(pattern.IsMatch("File1_000_000_1.png"));
Assert.IsTrue(pattern.IsMatch("File1_000_000#2.png"));
Assert.IsTrue(pattern.IsMatch("File1_000_000_1#2.png"));
Assert.IsTrue(pattern.IsMatch("File1_000_000[text].png"));
Assert.IsTrue(pattern.IsMatch("File1_000_000[text]_1.png"));
Assert.IsTrue(pattern.IsMatch("File1_000_000[text]#2.png"));
Assert.IsTrue(pattern.IsMatch("File1_000_000[text]_1#2.png"));
Assert.IsFalse(pattern.IsMatch("File1_000_000[text]_#2.png"));
}
Upvotes: 0
Reputation: 3960
Based on you "valid format", this will do the trick
^(?i)([a-z]{4}[2-7](_\d{3}){2}(\[.*?[^0-9]\])?(_\d{1,3}?)?(#\d{1,3}?)?\.png)$
remove (?i) to make the match case sensitive, and change [2-7] to [1-7] to make it match the files you gave (you said valid were 2-7, but your sample files are File1...)
Upvotes: 1
Reputation: 41757
A question on regex that doesn't involve HTML parsing, is a rarity!
Try the following:
@"^.{4}[2-7](_\d{3}){2}(\[.*?\])?(_\d{1,3})?(#\d{1,3})?\.png$"
This breaks down into:
^ Start of string
.{4} Any character, exactly 4 times
[2-7] A number in the range 2 - 7 once
(_\d{3}){2} An underscore followed by 3 numbers, twice
(\[.*?\])? An opening square bracket followed by any number of characters and closed by a square bracket 0 or 1 times
(_\d{1,3})? An underscore followed by at least 1 and up to 3 numbers 0 or 1 times
(#\d{1,3})? A pound (#) followed by at least 1 and up to 3 numbers 0 or 1 times
\.png$ Ending in .png
Upvotes: 2
Reputation: 224913
I'll just rewrite one, here:
^.{4}[2-7](_\d{3}){2}(\[[^\]]*\])?(_\d{1,3})?(\#\d{1,3})?\.png$
The problem right now is that you're not matching .png
and you're not anchoring the end - the match ends prematurely. Also, you can avoid the double-escaping by prefixing your string with @
:
@"^.{4}[2-7](_\d{3}){2}(\[[^\]]*\])?(_\d{1,3})?(\#\d{1,3})?\.png$"
Upvotes: 2