簡體   English   中英

c#嵌套量詞-模式中的多個“?”

[英]c# Nested quantifier - multiple “?” in the pattern

我試圖查找目錄中是否至少有一個文件與模式匹配(僅使用“?”和“ *”通配符),但是某些組合會不斷拋出嵌套的限定符錯誤。 例如TestCashFile_10_12-25-2016????????.c?? 不起作用。

這些模式來自非技術用戶(他們對這兩個通配符的基本用法有所了解),因此“?” 和“ *”幾乎可以放在文件名中的任何地方,我沒有太多控制權。

這些模式有什么問題?

這是運行此正則表達式的C#代碼段-

string fileName = C:\TestFiles\TestCashFile_10_12-25-2016????????.c??'
string directory = Path.GetDirectoryName(fileName);
string[] temp = fileName.Split('\\');
string file = temp[temp.Length - 1];
var found = Directory.GetFiles(directory).Any(p => Regex.Match(p, file).Success);

更新-這個問題已經解決,但是如果它可以幫助其他人尋找類似的東西,只是為了澄清-在這種情況下,我想要“?” 表示必須完全有一個元素(而不是零或一個元素)。

? 運算符指定前一個元素可以出現0或1次。

https://msdn.microsoft.com/zh-CN/library/az24scfc(v=vs.110).aspx

匹配上一個元素零或一次。 “ rai?n”,“ ran”,“ rain”

如果您使用Directory.GetFiles內置的通配符(如@Ed Plunkett所述),則其工作方式應與您要查找的類似。

如果您仍想將當前方法與RegEx一起使用,請執行以下操作:

  • .* -任意數量的字符
  • .{n} -用期望的字符數替換n
  • .{m,n} -用最少的預期字符數替換m用最多的預期字符數替換n。

如果你需要 ”??” 要恰好匹配任何兩個字符,那么您是對的,您將必須使用正則表達式。 文件系統通配符對待“?” 為“零或任何字符之一”。

但是您無法按照您嘗試的方式進行操作,因為您是在向用戶詢問文件系統通配符-您只是在稍微改變一下語義。 您必須將用戶的字符串轉換為所需的正則表達式:

a???.*

必須成為

a.?.?.?\..*
  • 每個問號都變成“。”:完全是任何字符之一。
  • 每個“。” 成為“。”,因為未轉義的“。” 是正則表達式中的特殊字符。
  • 每個“ ”都必須變成“。 ”:零個或多個任何字符(猜測這個字符)。

file字符串執行此file ,然后執行.Any(p => Regex.Match(p, file).Success); 應該管用。

如果運行時有些慢,您可能需要編譯正則表達式:

file = TranslateWildcardsToRegex(file);
var re = new Regex(file);

var found = Directory.GetFiles("").Any(p => re.IsMatch(p));

我認為這對TranslateWildcardsToRegex()是正確的:

public static String TranslateWildcardsToRegex(String s)
{
    StringBuilder sb = new StringBuilder();

    foreach (var ch in s)
    {
        switch (ch)
        {
            case '?':
                sb.Append(".");
                break;

            case '*':
                sb.Append(".*");
                break;

            //  Escape a variety of characters that 
            //  mean something special in a regex
            case '(':
            case ')':
            case '{':
            case '}':
            case '[':
            case ']':
            case '.':
                sb.Append("\\" + ch);
                break;

            default:
                sb.Append(ch);
                break;
        }
    }

    return sb.ToString();
}

更新

在評論中,@ spender提供了一種更好,更干凈的方法來執行相同的操作:

var reStr = Regex.Escape(someWildcardThing).Replace(@"\?", ".").Replace(@"\*", ".*")

這些年來,除了自己仍然是一名正在恢復的C程序員之外,我沒有一個很好的借口不要自己這樣做。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM