Does anybody know a C# library for matching human readable patterns? Similar to regex, but friendlier?
Given a string value, I want to be able to match it against a pattern along the lines of:
(this AND that) OR "theother"
where "this" and "that" are LIKE expressions, and "theother" is an exact match due to the quotes.
UPDATE: Ok, just to be a little bit clearer. The reason I want this is to allow end users to enter in their own patterns, as string v开发者_JAVA技巧alues. So I'm after something that works in a similar way to regex, but uses human readable strings that my users will easily understand
var pattern = "(this AND that) OR \"theother\""; // Could be fetched from textbox
var match = SomeLib.IsMatch(myString, pattern);
I read this article a while back. It sounds along the lines of what you are asking.
Readable Regular Expressions
Which, looking at your request, you would then need to create a mapping of 'user friendly' terminology and this library's fluent interface.
It's an extra layer of abstraction, true but I personally, would rather read a fluent 'intermediate stage' than auto generated regex :s
There is a good library called VerbalExpressions that basically constructs RegEx from a Fluent expression. Here is an example:
// Create an example of how to test for correctly formed URLs
var verbEx = new VerbalExpressions()
.StartOfLine()
.Then( "http" )
.Maybe( "s" )
.Then( "://" )
.Maybe( "www." )
.AnythingBut( " " )
.EndOfLine();
// Create an example URL
var testMe = "https://www.google.com";
Assert.IsTrue(verbEx.Test( testMe ), "The URL is incorrect");
Well, after a lot of searching, I wasn't able to find exactly what I was after, but needing to get something working pretty quickly, and due to the fact the system I'm using already has the relevant DLLs, I've ended up using Lucene.NET to created a temporary index containing a single document with the relevant fields I need to search added to it. I can then do the type of query I'm after against it, and check for any matches. By using the RAMDirectory class I was able to create the index in memory, and dispose of it after the lookup, so no index files have to be written to disk.
I'm sure there are probably less intensive ways to achieve this, but as I say, it's the best I could come up with in the time I had.
Thank to everyone for their suggestions, and I would still like to know if there is a better way of doing this?
Several years ago I was looking for a way to define a more readable/intuitive syntax for the full-text search queries (SQL Server FTS). Then I found this article: Normalizing SQL Server Full-text Search Conditions.
I hope it could be as helpful for you as it was for me.
What you want is for users to just type in their search criteria just like they would in Google. Some words, maybe some quoted phrases, maybe a few operators, and have it just work. So, what to do? Well, you could try and parse and rearrange the mixed bag of crap your users will submit into a valid normal form that CONTAINS and CONTAINSTABLE will accept.
What about this?
Change this:
Regex socialSecurityNumberCheck = new Regex(@"^\d{3}-?\d{2}-?\d{4}$");
for this:
Regex socialSecurityNumberCheck = new Regex(Pattern.With.AtBeginning
.Digit.Repeat.Exactly(3)
.Literal("-").Repeat.Optional
.Digit.Repeat.Exactly(2)
.Literal("-").Repeat.Optional
.Digit.Repeat.Exactly(4)
.AtEnd);
Download the binary here: http://flimflan.com/files/ReadableRex_DLL.zip
Visual Basic has a LIKE operator. It is much friendlier than RegEx. When I code in VB.NET, I can usually completely eliminate the need for RegEx by using LIKE. In C#, you can either painfully deal with RegEx or create a VB library that uses the friendlier LIKE and reference it in your C# project.
Note: you will have to use RegEx for complex matching, but LIKE deals with most cases you run across.
I think C# has already human readable pattern matcher - it's called LINQ.
For example- LIKE
operator can be emulated like this:
public static void Main (string[] args) {
var found = "blood fold boot goat cook hole door".
Split(' ').
Where(part => part.Contains("oo"));
foreach (var part in found)
Console.WriteLine(part);
}
cheers!
精彩评论