【问题标题】:Regular expression wildcard [duplicate]正则表达式通配符[重复]
【发布时间】:2013-02-22 22:02:50
【问题描述】:

我刚开始使用Regular Expressions,这太让人不知所措了,即使在阅读了文档之后,我似乎也找不到从哪里开始帮助解决我的问题。

我必须要一堆字符串。

 "Project1 - Notepad"
 "Project2 - Notepad"
 "Project3 - Notepad"
 "Untitled - Notepad"
 "HeyHo - Notepad"

我有一个包含通配符的字符串。

"* - Notepad"

如果我将这些字符串中的任何一个与包含通配符的字符串进行比较,它就会返回 true。 (使用Regex.IsMatch() 或类似的东西..)

我通常不会要求这样的答案,但我就是找不到我需要的东西。有人能指出我正确的方向吗?

【问题讨论】:

  • 您要“比较”的字符串是静态字符串、用户输入等吗?换句话说,它会一直是* - Notepad(或类似的),还是可以在运行时修改?
  • 通配符是.*. 是任何东西,* 是重复零次或多次)
  • 它将是用户输入的字符串。它可以将 Project1 - Notepad 与 Project1 - Notepad 进行比较。但是用户可以选择使用通配符包含所有记事本项目
  • 此处发布了类似的问题。希望对您有所帮助:stackoverflow.com/questions/10400844/…
  • 您是否要匹配以“-记事本”结尾的任何内容?

标签: c# regex string wildcard


【解决方案1】:

通配符* 等效于正则表达式模式".*"(贪婪)或".*?"(非贪婪),因此您需要执行string.Replace()

string pattern = Regex.Escape(inputPattern).Replace("\\*", ".*?");

注意开头的Regex.Escape(inputPattern)。由于inputPattern 可能包含正则表达式使用的特殊字符,您需要正确转义这些字符。如果你不这样做,你的模式就会爆炸。

Regex.IsMatch(input, ".NET"); // may match ".NET", "aNET", "FNET", "7NET" and many more

因此,通配符 * 被转义为 \\*,这就是我们替换转义的通配符而不仅仅是通配符本身的原因。


使用模式

你可以做到:

Regex.IsMatch(input, pattern);

var regex = new Regex(pattern);
regex.IsMatch(input);

贪心和不贪心的区别

不同之处在于模式将尝试匹配多少。

考虑以下字符串:"hello (x+1)(x-1) world"。您想匹配左括号 ( 和右括号 ) 以及两者之间的任何内容。

Greedy 将仅匹配 "(x+1)(x-1)" 而不匹配其他内容。它基本上匹配它可以找到的最长的子字符串。

Not-greedy 将匹配 "(x+1)""(x-1)",仅此而已。换句话说:尽可能短的子字符串。

【讨论】:

  • 所以在这种情况下,字符串模式将是 * - Notepad ?
  • @PhaDaPhunk 假设inputPattern 是“* - 记事本”,string pattern 将是“.*? - 记事本”。但请记住,如果myString 包含正则表达式识别的其他特殊字符,例如. [ ( ) ] \ * + ?,您的模式将会非常混乱。
  • 如果我不得不使用这些字符,比如“?”要么 ”。”有什么办法吗?
  • @BKSpureon。这是原始模式:"* - Notepad"。在正则表达式中,星号 * 匹配前一个字符 0 次或多次,因此 "hell*world" 可以匹配 "helworld""hellworld""helllworld""hellllworld" 等。如果要匹配 "helloworld""hello world" 或类似的,您需要将原始模式(inputPattern)中的* 替换为.*.*?
  • 使用string pattern = Regex.Escape(inputPattern).Replace("*", ".*?");。否则,如果模式已经包含一些正则表达式特殊字符(例如点),则结果将无效。
【解决方案2】:

我刚刚写的很快(基于Validate that a string contain some exact words

    static void Main()
    {
        string[] inputs = 
        {
            "Project1 - Notepad", // True
            "Project2 - Notepad", // True
            "HeyHo - Notepad", // True
            "Nope - Won't work" // False
        };

        const string filterParam = "Notepad";
        var pattern = string.Format(@"^(?=.*\b - {0}\b).+$", filterParam);

        foreach (var input in inputs)
        {
            Console.WriteLine(Regex.IsMatch(input, pattern));
        }
        Console.ReadLine();
    }

【讨论】:

  • 效果很好!唯一的问题是,因为记事本将是可变的,使用类似这样的东西:@"^(?=.*\b - " + variableContainingNotepad + "\b).+$" 来更改单词记事本似乎不起作用,因为“+”字符
  • 使用 string.Format,我会更新我的第一篇文章。
【解决方案3】:

你应该这样做:

string myPattern = "* - Notepad";
foreach(string currentString in myListOfString)
    if(Regex.IsMatch(currentString, myPattern, RegexOptions.Singleline){
        Console.WriteLine("Found : "+currentString);
    }
}

顺便说一句,我看到你来自蒙特利尔,额外的法语文档 + 有用的工具: http://www.olivettom.com/?p=84

祝你好运!

【讨论】:

    【解决方案4】:

    看起来你想要的模式如下:

    /^.+-\s*Notepad$/
    

    如果它以“-记事本”结尾,则此模式将匹配整个字符串。

    【讨论】:

    • 太棒了。感谢您的回答。这是不需要所有这些额外解释的确切正则表达式
    猜你喜欢
    • 2013-12-16
    • 2016-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-03
    • 2012-12-01
    • 1970-01-01
    相关资源
    最近更新 更多