开发者

RegEx - Please help in forming this RegEx

Can you please help me to write regular expression for this.

Name = "Windows Product for .Net"

Type = "Software Programming"

Quantity = "Pack of 3"

I want to do a m开发者_C百科atch like this in c# for which I need RegEx.

If Name.contains(".Net") && (Type.Contains("Programming") || Type.Contains("Hardware")
{
// output will be a Match.
}
else 
{
// no match.
}

The approach I want to take here is , specify regular expression for each condition and then apply logical operand && , logical grouping paranthesis and then logical operand ||. I have come up with all regular expressions for these. How can I provide logical operands for each of them to execute in appropriate order?

   string Name = "Windows Product for .Net";
   string Type = "Software Programming";

   string patternForName = ".*Net";
   Regex rgxName = new Regex(patternForName);
   Match matchName = rgx.Match(Name);
   string patternForType = ".*Programming";
   Regex rgxType = new Regex(patternForType);
   Match matchType = rgx.Match(Type);

   string patternForType1 = ".*Hardware";
   Regex rgxType1 = new Regex(patternForType1);
   Match matchType1 = rgx.Match(Type);

Please note - We are making it dynamic, in the sense the patterns , operands and regEx are coming from xml file. So that's why I do not want to write one big regEx for above.


First of all you don't need a leading .* in your expression unless you want the whole match (i.e. when working with matches). Just for a simple "is it there" you won't need it as the pattern might match any position.

Just use one regular expression for each field (i.e. one for Name, one for Type, one for Quantity:

string patternForName = "\\.Net"; // escaping the dot so it will match real dots only
string patternForType = "Programming|Hardware"; // | will result in "left side or right side"
string patternForQuantity = ".?"; // will match any string, even empty ones

To check everything:

bool match = rgxName.IsMatch(Name) && rgxType.IsMatch(Type) && rgx.IsMatch(Quantity);


You can make them dynamic without using regex. Using regex won't really save you any time or effort, since the code's going to be about the same size either way. Following your pattern above, you can do something like this:

var names = new[] { "Net", "Programming" };
var types = new[] { "Hardware" };

bool matchFound = true;

foreach (string n in names)
    matchFound &= Name.Contains(n);

foreach (string t in types)
    matchFound |= Type.Contains(t);

The above code assumes you want to match all of "names" and any of "types", but you can substitute any logic you want.

The real crux of your problem is these boolean combinations; regex won't help you with the logic for those, so you're better off using string.Contains unless the patterns you're looking for become much more variable. Regex is distracting you from your real goal here, in my opinion.


It sounds like you're asking how you should handle the logical part of the problem. If you're pulling it from an xml file, you could structure your file in the way you want to structure your logic.

for example, have And and Or groups:

<And>
   <Name Match=".Net"/>
   <Or>
      <Type Match="Programming"/>
      <Type Match="Hardware"/>
   </Or>
</And>

Create classes for each of these types. For brevity, I didnt define the classes with properties or create constructors, but you can fill them out however you want:

class YourType
{
   string Name;
   string Type;
   string Quantity;
}

abstract class Test
{
   public abstract bool RunTest(YourType o);
}

class AndTest : Test
{
   public List<Test> Children;
   public bool RunTest(YourType o)
   {
      foreach (var test in Children)
      {
         if (!test.RunTest(o)) return false;
      }
      return true;
   }
}

class OrTest : Test
{
   public List<Test> Children;
   public bool RunTest(YourType o)
   {
      foreach (var test in Children)
      {
         if (test.RunTest(o)) return true;
      }
      return false;
   }
}

class NameTest : Test
{
   public string Match;

   public bool RunTest(YourType o)
   {
      return o.Name.Contains(Match);
   }
}

class TypeTest : Test
{
   public string Match;

   public bool RunTest(YourType o)
   {
      return o.Type.Contains(Match);
   }
}

Build the class structure from the xml file and just call RunTest from the top level Test. This way you can do any type of logic youd like. I just used Contains instead of a Regex for ease of the example, but you can easily replace the string match with a regex match.


if (rgxName.IsMatch(Name) && (rgxType.IsMatch(Type) || rgxType1.IsMatch(Type))
{
...
}


In .NET, Regex.Match matches anywhere in the string, so you don't need the any-characters (.*) prefix on your pattern. So, to check for ".NET", it would simply be:

Regex regexName = new Regex(@"\.NET", RegexOptions.IgnoreCase);
// IsMatch returns true/false, Match returns a Match object
bool nameMatches = regexName.IsMatch(name);

Your patterns for Programming and Hardware would just be

new Regex(@"Programming", RegexOptions.IgnoreCase) // Or leave out IgnoreCase if you're case-sensitive
new Regex(@"Hardware")

If you have a list of Name patterns and a list of type patterns, you could do something similar to this:

bool nameIsMatch = false;
bool typeIsMatch = false;

foreach (string namePattern in namePatterns)
{
    nameIsMatch = nameIsMatch || Regex.IsMatch(nameString, namePattern);
}

foreach (string typePattern in typePatterns)
{
    typeIsMatch = typeIsMatch || Regex.IsMatch(typeString, typePattern);
}

if (nameIsMatch && typeIsMatch)
{
    // Whatever you want to do
}


patternForName = ".Net" patternForType = "Programming" patternForType1 = "Hardware"

You might find The Regex Coach to be useful.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜