64

Is there any way to search patterns in strings in C#?

Something like Sql LIKE would be very useful.

Ahmet Altun
  • 3,910
  • 9
  • 39
  • 64

19 Answers19

80

Regular expressions allow for everything that LIKE allows for, and much more, but have a completely different syntax. However, since the rules for LIKE are so simple(where % means zero-or-more characters and _ means one character), and both LIKE arguments and regular expressions are expressed in strings, we can create a regular expression that takes a LIKE argument (e.g. abc_ef% *usd) and turn it into the equivalent regular expression (e.g. \Aabc.ef.* \*usd\z):

@"\A" + new Regex(@"\.|\$|\^|\{|\[|\(|\||\)|\*|\+|\?|\\").Replace(toFind, ch => @"\" + ch).Replace('_', '.').Replace("%", ".*") + @"\z"

From that we can build a Like() method:

public static class MyStringExtensions
{
  public static bool Like(this string toSearch, string toFind)
  {
    return new Regex(@"\A" + new Regex(@"\.|\$|\^|\{|\[|\(|\||\)|\*|\+|\?|\\").Replace(toFind, ch => @"\" + ch).Replace('_', '.').Replace("%", ".*") + @"\z", RegexOptions.Singleline).IsMatch(toSearch);
  }
}

And hence:

bool willBeTrue = "abcdefg".Like("abcd_fg");
bool willAlsoBeTrue = "abcdefg".Like("ab%f%");
bool willBeFalse = "abcdefghi".Like("abcd_fg");
Jon Hanna
  • 110,372
  • 10
  • 146
  • 251
  • 1
    No, in SQL that yields false (try it in such SQL databases as Oracle or PostgreSQL). In T-SQL it yields true, not because of escape characters (there are none involved here), but because of character range specifier's. This non-standard extension could certainly be added if you wanted. – Jon Hanna Feb 08 '12 at 14:40
  • I found the bug in the MyStringExpessions.Like() function. When it builds Regex it adds backslash in front of [...] which breaks it. I deleted "\[|" from above string and everything seems to work. – Gregory Khrapunovich Oct 23 '13 at 14:26
  • I also had to delete "\^|" – Gregory Khrapunovich Oct 23 '13 at 14:58
  • 1
    Unfortunly, is not working, `Like("abc", "[a-z]%")` returns `false` – Alex Zhukovskiy Mar 14 '17 at 17:41
  • 2
    @AlexZhukovskiy precisely as it should do. – Jon Hanna Mar 14 '17 at 18:10
  • 1
    @AlexZhukovskiy note that a method that duplicated T-SQL's non-standard additions to `LIKE` would return `true` there, but this is a method duplicating SQL's `LIKE`. – Jon Hanna Mar 14 '17 at 18:12
  • @JonHanna that's teoretically correct, but still have limited usage. For example I have written a query with `SqlMethods.Like` but was unable to run query that uses it until I found your post and fixed some issues (difference between T-SQL and ANSI SQL syntax). Most of C# developers are using T-SQL so I think it would be useful to add an alternative for them. – Alex Zhukovskiy Mar 15 '17 at 09:31
  • 1
    Instead of trying to match all chars that needs escaping, wouldn't it be better to use `Regex.Escape` instead? [also documentation for `\A` and `\z` usages](https://learn.microsoft.com/en-us/dotnet/standard/base-types/regular-expression-language-quick-reference) – NiKiZe Oct 10 '17 at 18:52
  • @JonHanna Tried to use wildcards * instead of %. By replacing `Replace("*", ".*")` but it doesn't work.. – Siyon DP Oct 29 '18 at 10:06
48

There are couple of ways you can search as "LIKE" operator of SQL in C#. If you just want to know whether the pattern exists in the string variable, you can use

string value = "samplevalue";
value.Contains("eva"); // like '%eva%'
value.StartsWith("eva");  // like 'eva%'
value.EndsWith("eva"); // like '%eva'

if you want to search the pattern from a list of string, you should use LINQ to Object Features.

List<string> valuee = new List<string> { "samplevalue1", "samplevalue2", "samplevalue3" };
List<string> contains = (List<string>) (from val in valuee
                                        where val.Contains("pattern")
                                        select val); // like '%pattern%'

List<string> starts = (List<string>) (from val in valuee
                                      where val.StartsWith("pattern")
                                      select val); // like 'pattern%'

List<string> ends = (List<string>) (from val in valuee                          
                                    where val.EndsWith ("pattern")
                                    select val); // like '%pattern'
The_Black_Smurf
  • 5,178
  • 14
  • 52
  • 78
Foyzul Karim
  • 4,252
  • 5
  • 47
  • 70
21

When I ran into this on a contract, I had no other option than to have a 100% compliant TransactSQL LIKE function. Below is the result - a static function and a string extension method. I'm sure it can be optimized further, but it's pretty fast and passed my long list of test scenarios. Hope it helps someone!

using System;
using System.Collections.Generic;

namespace SqlLikeSample
{
    public class TestSqlLikeFunction
    {
        static void Main(string[] args)
        {
            TestSqlLikePattern(true, "%", "");
            TestSqlLikePattern(true, "%", " ");
            TestSqlLikePattern(true, "%", "asdfa asdf asdf");
            TestSqlLikePattern(true, "%", "%");
            TestSqlLikePattern(false, "_", "");
            TestSqlLikePattern(true, "_", " ");
            TestSqlLikePattern(true, "_", "4");
            TestSqlLikePattern(true, "_", "C");
            TestSqlLikePattern(false, "_", "CX");
            TestSqlLikePattern(false, "[ABCD]", "");
            TestSqlLikePattern(true, "[ABCD]", "A");
            TestSqlLikePattern(true, "[ABCD]", "b");
            TestSqlLikePattern(false, "[ABCD]", "X");
            TestSqlLikePattern(false, "[ABCD]", "AB");
            TestSqlLikePattern(true, "[B-D]", "C");
            TestSqlLikePattern(true, "[B-D]", "D");
            TestSqlLikePattern(false, "[B-D]", "A");
            TestSqlLikePattern(false, "[^B-D]", "C");
            TestSqlLikePattern(false, "[^B-D]", "D");
            TestSqlLikePattern(true, "[^B-D]", "A");
            TestSqlLikePattern(true, "%TEST[ABCD]XXX", "lolTESTBXXX");
            TestSqlLikePattern(false, "%TEST[ABCD]XXX", "lolTESTZXXX");
            TestSqlLikePattern(false, "%TEST[^ABCD]XXX", "lolTESTBXXX");
            TestSqlLikePattern(true, "%TEST[^ABCD]XXX", "lolTESTZXXX");
            TestSqlLikePattern(true, "%TEST[B-D]XXX", "lolTESTBXXX");
            TestSqlLikePattern(true, "%TEST[^B-D]XXX", "lolTESTZXXX");
            TestSqlLikePattern(true, "%Stuff.txt", "Stuff.txt");
            TestSqlLikePattern(true, "%Stuff.txt", "MagicStuff.txt");
            TestSqlLikePattern(false, "%Stuff.txt", "MagicStuff.txt.img");
            TestSqlLikePattern(false, "%Stuff.txt", "Stuff.txt.img");
            TestSqlLikePattern(false, "%Stuff.txt", "MagicStuff001.txt.img");
            TestSqlLikePattern(true, "Stuff.txt%", "Stuff.txt");
            TestSqlLikePattern(false, "Stuff.txt%", "MagicStuff.txt");
            TestSqlLikePattern(false, "Stuff.txt%", "MagicStuff.txt.img");
            TestSqlLikePattern(true, "Stuff.txt%", "Stuff.txt.img");
            TestSqlLikePattern(false, "Stuff.txt%", "MagicStuff001.txt.img");
            TestSqlLikePattern(true, "%Stuff.txt%", "Stuff.txt");
            TestSqlLikePattern(true, "%Stuff.txt%", "MagicStuff.txt");
            TestSqlLikePattern(true, "%Stuff.txt%", "MagicStuff.txt.img");
            TestSqlLikePattern(true, "%Stuff.txt%", "Stuff.txt.img");
            TestSqlLikePattern(false, "%Stuff.txt%", "MagicStuff001.txt.img");
            TestSqlLikePattern(true, "%Stuff%.txt", "Stuff.txt");
            TestSqlLikePattern(true, "%Stuff%.txt", "MagicStuff.txt");
            TestSqlLikePattern(false, "%Stuff%.txt", "MagicStuff.txt.img");
            TestSqlLikePattern(false, "%Stuff%.txt", "Stuff.txt.img");
            TestSqlLikePattern(false, "%Stuff%.txt", "MagicStuff001.txt.img");
            TestSqlLikePattern(true, "%Stuff%.txt", "MagicStuff001.txt");
            TestSqlLikePattern(true, "Stuff%.txt%", "Stuff.txt");
            TestSqlLikePattern(false, "Stuff%.txt%", "MagicStuff.txt");
            TestSqlLikePattern(false, "Stuff%.txt%", "MagicStuff.txt.img");
            TestSqlLikePattern(true, "Stuff%.txt%", "Stuff.txt.img");
            TestSqlLikePattern(false, "Stuff%.txt%", "MagicStuff001.txt.img");
            TestSqlLikePattern(false, "Stuff%.txt%", "MagicStuff001.txt");
            TestSqlLikePattern(true, "%Stuff%.txt%", "Stuff.txt");
            TestSqlLikePattern(true, "%Stuff%.txt%", "MagicStuff.txt");
            TestSqlLikePattern(true, "%Stuff%.txt%", "MagicStuff.txt.img");
            TestSqlLikePattern(true, "%Stuff%.txt%", "Stuff.txt.img");
            TestSqlLikePattern(true, "%Stuff%.txt%", "MagicStuff001.txt.img");
            TestSqlLikePattern(true, "%Stuff%.txt%", "MagicStuff001.txt");
            TestSqlLikePattern(true, "_Stuff_.txt_", "1Stuff3.txt4");
            TestSqlLikePattern(false, "_Stuff_.txt_", "1Stuff.txt4");
            TestSqlLikePattern(false, "_Stuff_.txt_", "1Stuff3.txt");
            TestSqlLikePattern(false, "_Stuff_.txt_", "Stuff3.txt4");

            Console.ReadKey();
        }

        public static void TestSqlLikePattern(bool expectedResult, string pattern, string testString)
        {
            bool result = testString.SqlLike(pattern);
            if (expectedResult != result)
            {
                Console.ForegroundColor = ConsoleColor.Red; System.Console.Out.Write("[SqlLike] FAIL");
            }
            else
            {
                Console.ForegroundColor = ConsoleColor.Green; Console.Write("[SqlLike] PASS");
            }
            Console.ForegroundColor = ConsoleColor.White; Console.WriteLine(": \"" + testString + "\" LIKE \"" + pattern + "\" == " + expectedResult);
        }
    }

    public static class SqlLikeStringExtensions
    {
        public static bool SqlLike(this string s, string pattern)
        {
            return SqlLikeStringUtilities.SqlLike(pattern, s);
        }
    }

    public static class SqlLikeStringUtilities
    {
        public static bool SqlLike(string pattern, string str)
        {
            bool isMatch = true,
                isWildCardOn = false,
                isCharWildCardOn = false,
                isCharSetOn = false,
                isNotCharSetOn = false,
                endOfPattern = false;
            int lastWildCard = -1;
            int patternIndex = 0;
            List<char> set = new List<char>();
            char p = '\0';

            for (int i = 0; i < str.Length; i++)
            {
                char c = str[i];
                endOfPattern = (patternIndex >= pattern.Length);
                if (!endOfPattern)
                {
                    p = pattern[patternIndex];

                    if (!isWildCardOn && p == '%')
                    {
                        lastWildCard = patternIndex;
                        isWildCardOn = true;
                        while (patternIndex < pattern.Length &&
                            pattern[patternIndex] == '%')
                        {
                            patternIndex++;
                        }
                        if (patternIndex >= pattern.Length) p = '\0';
                        else p = pattern[patternIndex];
                    }
                    else if (p == '_')
                    {
                        isCharWildCardOn = true;
                        patternIndex++;
                    }
                    else if (p == '[')
                    {
                        if (pattern[++patternIndex] == '^')
                        {
                            isNotCharSetOn = true;
                            patternIndex++;
                        }
                        else isCharSetOn = true;

                        set.Clear();
                        if (pattern[patternIndex + 1] == '-' && pattern[patternIndex + 3] == ']')
                        {
                            char start = char.ToUpper(pattern[patternIndex]);
                            patternIndex += 2;
                            char end = char.ToUpper(pattern[patternIndex]);
                            if (start <= end)
                            {
                                for (char ci = start; ci <= end; ci++)
                                {
                                    set.Add(ci);
                                }
                            }
                            patternIndex++;
                        }

                        while (patternIndex < pattern.Length &&
                            pattern[patternIndex] != ']')
                        {
                            set.Add(pattern[patternIndex]);
                            patternIndex++;
                        }
                        patternIndex++;
                    }
                }

                if (isWildCardOn)
                {
                    if (char.ToUpper(c) == char.ToUpper(p))
                    {
                        isWildCardOn = false;
                        patternIndex++;
                    }
                }
                else if (isCharWildCardOn)
                {
                    isCharWildCardOn = false;
                }
                else if (isCharSetOn || isNotCharSetOn)
                {
                    bool charMatch = (set.Contains(char.ToUpper(c)));
                    if ((isNotCharSetOn && charMatch) || (isCharSetOn && !charMatch))
                    {
                        if (lastWildCard >= 0) patternIndex = lastWildCard;
                        else
                        {
                            isMatch = false;
                            break;
                        }
                    }
                    isNotCharSetOn = isCharSetOn = false;
                }
                else
                {
                    if (char.ToUpper(c) == char.ToUpper(p))
                    {
                        patternIndex++;
                    }
                    else
                    {
                        if (lastWildCard >= 0) patternIndex = lastWildCard;
                        else
                        {
                            isMatch = false;
                            break;
                        }
                    }
                }
            }
            endOfPattern = (patternIndex >= pattern.Length);

            if (isMatch && !endOfPattern)
            {
                bool isOnlyWildCards = true;
                for (int i = patternIndex; i < pattern.Length; i++)
                {
                    if (pattern[i] != '%')
                    {
                        isOnlyWildCards = false;
                        break;
                    }
                }
                if (isOnlyWildCards) endOfPattern = true;
            }
            return isMatch && endOfPattern;
        }
    }
}
komma8.komma1
  • 1,250
  • 2
  • 14
  • 20
  • 2
    20x faster as a compiled RegEx method I used. Nice! – IvoTops Feb 06 '16 at 10:33
  • This is quite good but breaks on inappropriate patterns involving brackets. i.e. a pattern of `"["` will throw `IndexOutOfRangeException`. Syntax aside, it also doesn't support proper range expansion (this function assumes that you will have a single range and no other characters involved), the case of `LIKE '[a-cdf]'` from the doc won't work properly. It seems that the `-` needs to be the first character to be treated literally or perhaps the last character - the documentation doesn't specify. The doc is also unclear on how it handles goofy ranges, i.e. z-a, Z-z, etc. – Joel Feb 08 '18 at 13:22
  • I think there's also a very minor logic error in here. Consider the pattern `"_"` with the text `"__"`. With the logic as is, it skips the pattern portion after the wildcard applies to the first character since there's no more pattern to allocate (expected). Normally a 2-character input will be rejected by an underscore pattern by setting `isMatch` to `false`, but the `else if` where it compares the last pattern character to the input character gets hit which means the `else` for setting `isMatch` does not get hit. – Joel Feb 08 '18 at 16:54
15
myString.Contains("someString");  // equal to myString LIKE '%someString%'
myString.EndsWith("someString");  // equal to myString LIKE '%someString'
myString.StartsWith("someString");  // equal to myString LIKE 'someString%'
KirstieBallance
  • 1,238
  • 12
  • 26
M.R.Sadeghi
  • 336
  • 3
  • 16
5

Simply .Contains() would do the work for you.

"Example String".Contains("amp");   //like '%amp%'

This would return true, and performing a select on it would return the desired output.

Ali Shah Ahmed
  • 3,263
  • 3
  • 24
  • 22
4

Operators.LikeString

https://msdn.microsoft.com/en-us/library/microsoft.visualbasic.compilerservices.operators.likestring(v=vs.100).ASPX

public static bool LikeString(
    string Source,
    string Pattern,
    CompareMethod CompareOption
)
3

Have your tried

"This is a string".Contains("string");
Ash Burlaczenko
  • 24,778
  • 15
  • 68
  • 99
3

Check out Regular Expressions.

Daniel Earwicker
  • 114,894
  • 38
  • 205
  • 284
3

Contains maybe

if ("bla bli blu".Contains("blu")){......}
Guidhouse
  • 1,406
  • 11
  • 18
2

Check out this question - How to do SQL Like % in Linq?

Also, for more advanced string pattern searching, there are lots of tutorials on using Regular Expressions - e.g. http://www.codeproject.com/KB/dotnet/regextutorial.aspx

Community
  • 1
  • 1
Stuart
  • 66,722
  • 7
  • 114
  • 165
1

As a late but proper answer:

The closest thing there is to a SQL-Like function in C-Sharp is the implementation of a SQL-Like function in C#.

You can rip it out of http://code.google.com/p/csharp-sqlite/source/checkout
[root]/csharp-sqlite/Community.CsharpSqlite/src/func_c.cs

    /*
** Implementation of the like() SQL function.  This function implements
** the build-in LIKE operator.  The first argument to the function is the
** pattern and the second argument is the string.  So, the SQL statements:
**
**       A LIKE B
**
** is implemented as like(B,A).
**
** This same function (with a different compareInfo structure) computes
** the GLOB operator.
*/
    static void likeFunc(
    sqlite3_context context,
    int argc,
    sqlite3_value[] argv
    )
    {
      string zA, zB;
      u32 escape = 0;
      int nPat;
      sqlite3 db = sqlite3_context_db_handle( context );

      zB = sqlite3_value_text( argv[0] );
      zA = sqlite3_value_text( argv[1] );

      /* Limit the length of the LIKE or GLOB pattern to avoid problems
      ** of deep recursion and N*N behavior in patternCompare().
      */
      nPat = sqlite3_value_bytes( argv[0] );
      testcase( nPat == db.aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] );
      testcase( nPat == db.aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] + 1 );
      if ( nPat > db.aLimit[SQLITE_LIMIT_LIKE_PATTERN_LENGTH] )
      {
        sqlite3_result_error( context, "LIKE or GLOB pattern too complex", -1 );
        return;
      }
      //Debug.Assert( zB == sqlite3_value_text( argv[0] ) );  /* Encoding did not change */

      if ( argc == 3 )
      {
        /* The escape character string must consist of a single UTF-8 character.
        ** Otherwise, return an error.
        */
        string zEsc = sqlite3_value_text( argv[2] );
        if ( zEsc == null )
          return;
        if ( sqlite3Utf8CharLen( zEsc, -1 ) != 1 )
        {
          sqlite3_result_error( context,
          "ESCAPE expression must be a single character", -1 );
          return;
        }
        escape = sqlite3Utf8Read( zEsc, ref zEsc );
      }
      if ( zA != null && zB != null )
      {
        compareInfo pInfo = (compareInfo)sqlite3_user_data( context );
#if SQLITE_TEST
#if !TCLSH
        sqlite3_like_count++;
#else
        sqlite3_like_count.iValue++;
#endif
#endif
        sqlite3_result_int( context, patternCompare( zB, zA, pInfo, escape ) ? 1 : 0 );
      }
    }




    /*
    ** Compare two UTF-8 strings for equality where the first string can
    ** potentially be a "glob" expression.  Return true (1) if they
    ** are the same and false (0) if they are different.
    **
    ** Globbing rules:
    **
    **      '*'       Matches any sequence of zero or more characters.
    **
    **      '?'       Matches exactly one character.
    **
    **     [...]      Matches one character from the enclosed list of
    **                characters.
    **
    **     [^...]     Matches one character not in the enclosed list.
    **
    ** With the [...] and [^...] matching, a ']' character can be included
    ** in the list by making it the first character after '[' or '^'.  A
    ** range of characters can be specified using '-'.  Example:
    ** "[a-z]" matches any single lower-case letter.  To match a '-', make
    ** it the last character in the list.
    **
    ** This routine is usually quick, but can be N**2 in the worst case.
    **
    ** Hints: to match '*' or '?', put them in "[]".  Like this:
    **
    **         abc[*]xyz        Matches "abc*xyz" only
    */
    static bool patternCompare(
    string zPattern,            /* The glob pattern */
    string zString,             /* The string to compare against the glob */
    compareInfo pInfo,          /* Information about how to do the compare */
    u32 esc                     /* The escape character */
    )
    {
      u32 c, c2;
      int invert;
      int seen;
      int matchOne = (int)pInfo.matchOne;
      int matchAll = (int)pInfo.matchAll;
      int matchSet = (int)pInfo.matchSet;
      bool noCase = pInfo.noCase;
      bool prevEscape = false;     /* True if the previous character was 'escape' */
      string inPattern = zPattern; //Entered Pattern

      while ( ( c = sqlite3Utf8Read( zPattern, ref zPattern ) ) != 0 )
      {
        if ( !prevEscape && c == matchAll )
        {
          while ( ( c = sqlite3Utf8Read( zPattern, ref zPattern ) ) == matchAll
          || c == matchOne )
          {
            if ( c == matchOne && sqlite3Utf8Read( zString, ref zString ) == 0 )
            {
              return false;
            }
          }
          if ( c == 0 )
          {
            return true;
          }
          else if ( c == esc )
          {
            c = sqlite3Utf8Read( zPattern, ref zPattern );
            if ( c == 0 )
            {
              return false;
            }
          }
          else if ( c == matchSet )
          {
            Debug.Assert( esc == 0 );         /* This is GLOB, not LIKE */
            Debug.Assert( matchSet < 0x80 );  /* '[' is a single-byte character */
            int len = 0;
            while ( len < zString.Length && patternCompare( inPattern.Substring( inPattern.Length - zPattern.Length - 1 ), zString.Substring( len ), pInfo, esc ) == false )
            {
              SQLITE_SKIP_UTF8( zString, ref len );
            }
            return len < zString.Length;
          }
          while ( ( c2 = sqlite3Utf8Read( zString, ref zString ) ) != 0 )
          {
            if ( noCase )
            {
               if( 0==((c2)&~0x7f) )
                c2 = (u32)sqlite3UpperToLower[c2]; //GlogUpperToLower(c2);
               if ( 0 == ( ( c ) & ~0x7f ) )
                 c = (u32)sqlite3UpperToLower[c]; //GlogUpperToLower(c);
              while ( c2 != 0 && c2 != c )
              {
                c2 = sqlite3Utf8Read( zString, ref zString );
                if ( 0 == ( ( c2 ) & ~0x7f ) )
                  c2 = (u32)sqlite3UpperToLower[c2]; //GlogUpperToLower(c2);
              }
            }
            else
            {
              while ( c2 != 0 && c2 != c )
              {
                c2 = sqlite3Utf8Read( zString, ref zString );
              }
            }
            if ( c2 == 0 )
              return false;
            if ( patternCompare( zPattern, zString, pInfo, esc ) )
              return true;
          }
          return false;
        }
        else if ( !prevEscape && c == matchOne )
        {
          if ( sqlite3Utf8Read( zString, ref zString ) == 0 )
          {
            return false;
          }
        }
        else if ( c == matchSet )
        {
          u32 prior_c = 0;
          Debug.Assert( esc == 0 );    /* This only occurs for GLOB, not LIKE */
          seen = 0;
          invert = 0;
          c = sqlite3Utf8Read( zString, ref zString );
          if ( c == 0 )
            return false;
          c2 = sqlite3Utf8Read( zPattern, ref zPattern );
          if ( c2 == '^' )
          {
            invert = 1;
            c2 = sqlite3Utf8Read( zPattern, ref zPattern );
          }
          if ( c2 == ']' )
          {
            if ( c == ']' )
              seen = 1;
            c2 = sqlite3Utf8Read( zPattern, ref zPattern );
          }
          while ( c2 != 0 && c2 != ']' )
          {
            if ( c2 == '-' && zPattern[0] != ']' && zPattern[0] != 0 && prior_c > 0 )
            {
              c2 = sqlite3Utf8Read( zPattern, ref zPattern );
              if ( c >= prior_c && c <= c2 )
                seen = 1;
              prior_c = 0;
            }
            else
            {
              if ( c == c2 )
              {
                seen = 1;
              }
              prior_c = c2;
            }
            c2 = sqlite3Utf8Read( zPattern, ref zPattern );
          }
          if ( c2 == 0 || ( seen ^ invert ) == 0 )
          {
            return false;
          }
        }
        else if ( esc == c && !prevEscape )
        {
          prevEscape = true;
        }
        else
        {
          c2 = sqlite3Utf8Read( zString, ref zString );
          if ( noCase )
          {
            if ( c < 0x80 )
              c = (u32)sqlite3UpperToLower[c]; //GlogUpperToLower(c);
            if ( c2 < 0x80 )
              c2 = (u32)sqlite3UpperToLower[c2]; //GlogUpperToLower(c2);
          }
          if ( c != c2 )
          {
            return false;
          }
          prevEscape = false;
        }
      }
      return zString.Length == 0;
    }
Stefan Steiger
  • 78,642
  • 66
  • 377
  • 442
1

Use it like this:

if (lbl.Text.StartWith("hr")==true ) {…}
Kypros
  • 2,997
  • 5
  • 21
  • 27
chevhfghfghfgh
  • 127
  • 1
  • 6
1

This is my implementation - it passes the tests and does the trick - you may want to change the replacement token if you're using three tildes in your statements:

private Regex LikeExpressionToRegexPattern(String likePattern)
{
    var replacementToken = "~~~";

    String result = likePattern.Replace("_", replacementToken)
        .Replace("%", ".*");

    result = Regex.Replace(result, @"\[.*" + replacementToken + @".*\]", "_");

    result = result.Replace(replacementToken, ".");

    return new Regex("^" + result + "$", RegexOptions.IgnoreCase);
}

Example:

// Define a test string.
string text = "Hello stackoverflow world";

string like = "%flow%";

// Define a regular expression and Find matches.
MatchCollection matches = LikeExpressionToRegexPattern(like).Matches(text);

//Result.
if (matches.Count > 0) {
    //Yes
} else {
    //No
}
Checho Man
  • 45
  • 1
  • 1
  • 5
DavidWainwright
  • 2,895
  • 1
  • 27
  • 30
1

I think you can use "a string.Contains("str") for this.

it will search in a string to a patern, and result true is founded and false if not.

0

Add a VB.NET DLL encapsulating the VB.NET Like Operator

Peter Meinl
  • 2,566
  • 25
  • 39
0

As aready proposed in this answer and this other answer Microsoft.VisualBasic.CompilerServices.Operators.LikeString could be a good option for simple tasks, when a RegExp is overkill. Syntax is different from RegExp and SQL LIKE operator, but it's really simple to learn (mainly because it's also very limited).

Assembly Microsoft.VisualBasic must be added as a reference to the project to use this method.

For more information see Operators.LikeString Method and for a description of the syntax see Like Operator (Visual Basic).

It can be used as an extension method to String class:

/// <summary>
/// Visual Basic like operator. Performs simple, case insensitive, string pattern matching.
/// </summary>
/// <param name="thisString"></param>
/// <param name="pattern"> ? = Any single character. * = Zero or more characters. # = Any single digit (0–9)</param>
/// <returns>true if the string matches the pattern</returns>
public static bool Like(this string thisString, string pattern)
    => Microsoft.VisualBasic.CompilerServices.Operators
        .LikeString(thisString, pattern, Microsoft.VisualBasic.CompareMethod.Text);
Jordi
  • 2,055
  • 1
  • 16
  • 34
0
public static class StringsEx
{
    public static IEnumerable<String> Like(this IEnumerable<String> input, String pattern)
    {
        var dt = new DataTable();
        dt.Columns.Add("Search");
        foreach (String str in input)
        {
            dt.Rows.Add(str);
        }
        dt.DefaultView.RowFilter = String.Format("Search LIKE '{0}'", pattern);
        return dt.DefaultView.ToTable()
            .AsEnumerable()
            .Select(r => r.Field<String>("Search"));
    }
}

The only disadvantage is following: "Wildcard characters are not allowed in the middle of a string. For example, 'te*xt' is not allowed."©

QrystaL
  • 4,886
  • 2
  • 24
  • 28
0

there are several good answers here. to summarize what is already here and correct: using contains, startswith, endswith are good answers for most needs. regular expressions are what you want for more advanced needs.

something that is not mentioned in these answers, though, is that for a collection of strings, linq can be used to apply these filters in a call to the where method.

Dave Rael
  • 1,759
  • 2
  • 16
  • 21
-1
public static bool Like(this string value, string pattern)
{
    if (string.IsNullOrEmpty(value) || string.IsNullOrEmpty(pattern))
        return false;

    bool valid = true;
    string[] words = pattern.Split("*");
    int counter = words.Count();

    for (int i = 0; i < counter; i++)
    {
        valid = valid && value.StartsWith(words[i]);                
        value = value.Substring(words[i].Length);
    }
    return valid;
 }