Nice programing

Regex를 사용하여 문자열에서 와일드 카드 (* ,? 등) 검색을 수행해야합니다.

nicepro 2020. 12. 6. 22:06
반응형

Regex를 사용하여 문자열에서 와일드 카드 (* ,? 등) 검색을 수행해야합니다.


나는 (와일드 카드를 수행 할 필요가 *, ?등) 문자열을 검색하십시오. 이것이 내가 한 일입니다.

string input = "Message";
string pattern = "d*";
Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);

if (regex.IsMatch(input))
{
    MessageBox.Show("Found");
}
else
{
    MessageBox.Show("Not Found");
}

위의 코드를 사용하면 "Found"블록이 타격을 입지 만 실제로는 안됩니다!

내 패턴이 "e *"이면 "Found"만 히트해야합니다.

내 이해 또는 요구 사항은 d * 검색이 "d"다음에 모든 문자가 포함 된 텍스트를 찾아야한다는 것입니다.

패턴을 "d. *"및 "e. *"로 변경해야합니까? .NET에서 Regex 클래스를 사용하는 동안 내부적으로 수행하는 와일드 카드에 대한 지원이 있습니까?


에서 http://www.codeproject.com/KB/recipes/wildcardtoregex.aspx :

public static string WildcardToRegex(string pattern)
{
    return "^" + Regex.Escape(pattern)
                      .Replace(@"\*", ".*")
                      .Replace(@"\?", ".")
               + "$";
}

그래서 같은 foo*.xls?것이 ^foo.*\.xls.$.


LikeString이라는 Visual Basic 함수를 사용하여 RegEx없이 간단한 와일드 카드 마하를 수행 할 수 있습니다.

using Microsoft.VisualBasic;
using Microsoft.VisualBasic.CompilerServices;

if (Operators.LikeString("This is just a test", "*just*", CompareMethod.Text))
{
  Console.WriteLine("This matched!");
}

사용 CompareMethod.Text하면 대소 문자를 구분하지 않습니다. 대소 문자를 구분하는 비교를 위해 CompareMethod.Binary.

자세한 정보 : http://www.henrikbrinch.dk/Blog/2012/02/14/Wildcard-matching-in-C

MSDN : http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.compilerservices.operators.likestring%28v=vs.100%29.ASPX


글로브 표현의 올바른 정규 표현식 제제 d*^d수단을 시작으로 그 무엇과 일치하는 d.

    string input = "Message";
    string pattern = @"^d";
    Regex regex = new Regex(pattern, RegexOptions.IgnoreCase);

( @이 경우 인용은 필요하지 않지만 많은 정규 표현식이 혼자 남겨 두어야하는 백 슬래시 이스케이프를 사용하고 독자에게이 문자열이 특별 함을 나타 내기 때문에 좋은 방법입니다).


Windows와 * nux는 와일드 카드를 다르게 취급합니다. *, ?.Windows에서 매우 복잡한 방식으로 처리되어, 하나의 존재 또는 위치는 의미 다른 사람의를 변경합니다. * nux는 단순하게 유지하지만, 단지 하나의 단순한 패턴 일치 만 수행합니다. 그 외에도 Windows ?는 0 또는 1 문자와 일치하고 Linux는 정확히 1 문자와 일치합니다.

이 문제에 대한 권위있는 문서를 찾지 못했습니다. 여기에 Windows 8 / XP (명령 줄, dir특정 명령, Directory.GetFiles방법도 동일한 규칙 사용) 및 Ubuntu Server 12.04.1 에서 며칠 간의 테스트를 기반으로 한 결론 이 있습니다. ( ls명령). 실패한 사례도 많지만 일반적이고 흔하지 않은 수십 가지 사례를 작동하도록했습니다.

Gabe의 현재 답변은 * nux처럼 작동합니다. Windows 스타일도 원하고 불완전 함을 기꺼이 받아들이려면 여기에 있습니다.

    /// <summary>
    /// <para>Tests if a file name matches the given wildcard pattern, uses the same rule as shell commands.</para>
    /// </summary>
    /// <param name="fileName">The file name to test, without folder.</param>
    /// <param name="pattern">A wildcard pattern which can use char * to match any amount of characters; or char ? to match one character.</param>
    /// <param name="unixStyle">If true, use the *nix style wildcard rules; otherwise use windows style rules.</param>
    /// <returns>true if the file name matches the pattern, false otherwise.</returns>
    public static bool MatchesWildcard(this string fileName, string pattern, bool unixStyle)
    {
        if (fileName == null)
            throw new ArgumentNullException("fileName");

        if (pattern == null)
            throw new ArgumentNullException("pattern");

        if (unixStyle)
            return WildcardMatchesUnixStyle(pattern, fileName);

        return WildcardMatchesWindowsStyle(fileName, pattern);
    }

    private static bool WildcardMatchesWindowsStyle(string fileName, string pattern)
    {
        var dotdot = pattern.IndexOf("..", StringComparison.Ordinal);
        if (dotdot >= 0)
        {
            for (var i = dotdot; i < pattern.Length; i++)
                if (pattern[i] != '.')
                    return false;
        }

        var normalized = Regex.Replace(pattern, @"\.+$", "");
        var endsWithDot = normalized.Length != pattern.Length;

        var endWeight = 0;
        if (endsWithDot)
        {
            var lastNonWildcard = normalized.Length - 1;
            for (; lastNonWildcard >= 0; lastNonWildcard--)
            {
                var c = normalized[lastNonWildcard];
                if (c == '*')
                    endWeight += short.MaxValue;
                else if (c == '?')
                    endWeight += 1;
                else
                    break;
            }

            if (endWeight > 0)
                normalized = normalized.Substring(0, lastNonWildcard + 1);
        }

        var endsWithWildcardDot = endWeight > 0;
        var endsWithDotWildcardDot = endsWithWildcardDot && normalized.EndsWith(".");
        if (endsWithDotWildcardDot)
            normalized = normalized.Substring(0, normalized.Length - 1);

        normalized = Regex.Replace(normalized, @"(?!^)(\.\*)+$", @".*");

        var escaped = Regex.Escape(normalized);
        string head, tail;

        if (endsWithDotWildcardDot)
        {
            head = "^" + escaped;
            tail = @"(\.[^.]{0," + endWeight + "})?$";
        }
        else if (endsWithWildcardDot)
        {
            head = "^" + escaped;
            tail = "[^.]{0," + endWeight + "}$";
        }
        else
        {
            head = "^" + escaped;
            tail = "$";
        }

        if (head.EndsWith(@"\.\*") && head.Length > 5)
        {
            head = head.Substring(0, head.Length - 4);
            tail = @"(\..*)?" + tail;
        }

        var regex = head.Replace(@"\*", ".*").Replace(@"\?", "[^.]?") + tail;
        return Regex.IsMatch(fileName, regex, RegexOptions.IgnoreCase);
    }

    private static bool WildcardMatchesUnixStyle(string pattern, string text)
    {
        var regex = "^" + Regex.Escape(pattern)
                               .Replace("\\*", ".*")
                               .Replace("\\?", ".")
                    + "$";

        return Regex.IsMatch(text, regex);
    }

재미있는 점이 있습니다. Windows API PathMatchSpec 조차 FindFirstFile 과 일치하지 않습니다 . 그냥 시도 a1*., FindFirstFile그것이 일치라고 a1, PathMatchSpec하지 말한다.


d*0 개 이상의 " d"문자 와 일치해야 함을 의미합니다 . 따라서 모든 문자열은 유효한 일치입니다. d+대신 시도하십시오 !

와일드 카드 패턴을 지원하기 위해 와일드 카드를 RegEx 등가물로 대체합니다. 등이 *.*?됩니다 .?. 그러면 위의 표현은d.*


와일드 카드 식을 정규식으로 변환해야합니다. 예를 들면 :

    private bool WildcardMatch(String s, String wildcard, bool case_sensitive)
    {
        // Replace the * with an .* and the ? with a dot. Put ^ at the
        // beginning and a $ at the end
        String pattern = "^" + Regex.Escape(wildcard).Replace(@"\*", ".*").Replace(@"\?", ".") + "$";

        // Now, run the Regex as you already know
        Regex regex;
        if(case_sensitive)
            regex = new Regex(pattern);
        else
            regex = new Regex(pattern, RegexOptions.IgnoreCase);

        return(regex.IsMatch(s));
    } 

You must escape special Regex symbols in input wildcard pattern (for example pattern *.txt will equivalent to ^.*\.txt$) So slashes, braces and many special symbols must be replaced with @"\" + s, where s - special Regex symbol.


I think @Dmitri has nice solution at Matching strings with wildcard https://stackoverflow.com/a/30300521/1726296

Based on his solution, I have created two extension methods. (credit goes to him)

May be helpful.

public static String WildCardToRegular(this String value)
{
        return "^" + Regex.Escape(value).Replace("\\?", ".").Replace("\\*", ".*") + "$";
}

public static bool WildCardMatch(this String value,string pattern,bool ignoreCase = true)
{
        if (ignoreCase)
            return Regex.IsMatch(value, WildCardToRegular(pattern), RegexOptions.IgnoreCase);

        return Regex.IsMatch(value, WildCardToRegular(pattern));
}

Usage:

string pattern = "file.*";

var isMatched = "file.doc".WildCardMatch(pattern)

or

string xlsxFile = "file.xlsx"
var isMatched = xlsxFile.WildCardMatch(pattern)

All upper code is not correct to the end.

This is because when searching zz*foo* or zz* you will not get correct results.

And if you search "abcd*" in "abcd" in TotalCommander will he find a abcd file so all upper code is wrong.

Here is the correct code.

public string WildcardToRegex(string pattern)
{             
    string result= Regex.Escape(pattern).
        Replace(@"\*", ".+?").
        Replace(@"\?", "."); 

    if (result.EndsWith(".+?"))
    {
        result = result.Remove(result.Length - 3, 3);
        result += ".*";
    }

    return result;
}

You may want to use WildcardPattern from System.Management.Automation assembly. See my answer here.

참고URL : https://stackoverflow.com/questions/6907720/need-to-perform-wildcard-etc-search-on-a-string-using-regex

반응형