Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Regex to match the first file in a rar archive file set

Tags:

c#

regex

How do I do this? I've seen a solution not using a single regex for ruby becauase ruby doesn't support loookaround assertions. But is it possible in c#?

[Test]
public void RarArchiveFirstFileNameShouldMatch() {
    var regex = new Regex(@"\.(rar|001)$", RegexOptions.IgnoreCase | RegexOptions.Singleline);
    Assert.That(regex.IsMatch("filename.001"));
    Assert.That(regex.IsMatch("filename.rar"));
    Assert.That(regex.IsMatch("filename.part1.rar"));
    Assert.That(regex.IsMatch("filename.part01.rar"));
    Assert.That(regex.IsMatch("filenamepart44.rar"));
    Assert.That(regex.IsMatch("filename.004"), Is.False);
    Assert.That(regex.IsMatch("filename.057"), Is.False);
    Assert.That(regex.IsMatch("filename.r67"), Is.False);
    Assert.That(regex.IsMatch("filename.s89"), Is.False);
    Assert.That(regex.IsMatch("filename.part2.rar"), Is.False);
    Assert.That(regex.IsMatch("filename.part04.rar"), Is.False);
    Assert.That(regex.IsMatch("filename.part11.rar"), Is.False);
}
like image 384
MatteS Avatar asked Dec 01 '25 21:12

MatteS


2 Answers

This should pass your tests:

    var regex = new Regex(@"(\.001|\.part0*1\.rar|^((?!part\d*\.rar$).)*\.rar)$", RegexOptions.IgnoreCase | RegexOptions.Singleline);
    Assert.That(regex.IsMatch("filename.001"));
    Assert.That(regex.IsMatch("filename.rar"));
    Assert.That(regex.IsMatch("filename.part1.rar"));
    Assert.That(regex.IsMatch("filename.part01.rar"));
    Assert.That(regex.IsMatch("filename.004"), Is.False);
    Assert.That(regex.IsMatch("filename.057"), Is.False);
    Assert.That(regex.IsMatch("filename.r67"), Is.False);
    Assert.That(regex.IsMatch("filename.s89"), Is.False);
    Assert.That(regex.IsMatch("filename.part2.rar"), Is.False);
    Assert.That(regex.IsMatch("filename.part04.rar"), Is.False);
    Assert.That(regex.IsMatch("filename.part11.rar"), Is.False);
like image 157
Max Shawabkeh Avatar answered Dec 04 '25 09:12

Max Shawabkeh


You can do it in one regular expression, both in C# and in Ruby, but why bother?

You haven't really defined exactly what you want - first you should document that. Once you've documented it, it's easy to turn that description into ordinary code. I think that it is more readable and maintable this way:

/// <summary>
/// Returns true if a filename's extension is .001.
/// If the extensions is .rar, check to see if there is a part number
/// immediately before the extension.
/// If there is no part number, return true.
/// If there is a part number, returns true if the part number is 1.
/// In all other cases, return false.
/// </summary>
static bool isMainFile(string name)
{
    string extension = Path.GetExtension(name);
    if (extension == ".001")
        return true;
    if (extension != ".rar")
        return false;
    Match match = Regex.Match(name, @"\.part(\d+)\.rar$");
    if (!match.Success)
        return true;
    string partNumber = match.Groups[1].Value.TrimStart('0');
    return partNumber == "1";
}

I've left one regular expression in there as it's not too complex, and the alternative of fiddling with the Path functions seems clunky to me. Overall, I think the above code expresses the intention much more clearly than a regular expression does.

I do like it in when you can cleanly solve a problem with an elegant regular expression, but I'm not sure that a single regular expression is the best way to solve this problem.

like image 20
Mark Byers Avatar answered Dec 04 '25 10:12

Mark Byers



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!