【问题标题】:How to match this strings with Regex?如何将此字符串与正则表达式匹配?
【发布时间】:2009-08-09 07:04:43
【问题描述】:

基本上我有音乐文件名,例如:

<source> <target>

"Travis - Sing"   "Travis - Sing 2001.mp3"
"Travis - Sing"   "Travis - Sing Edit.mp3"
"Travis - Sing"   "Travis - Sing New Edit.mp3"
"Mission Impossible I"   "Mission Impossible I - Main Theme.mp3"
"Mission Impossible I"   "Mission Impossible II - Main Theme.mp3"
"Mesrine - Death Instinct"   "Mesrine - Death Instinct - Le Million.mp3"
"Mesrine - Public Enemy #1"   "Mesrine - Public Enemy #1 - Theme"
"Se7en"   "Se7en Motion Picture Soundtrack - Theme.mp3"

括号不包含在字符串中(仅用于演示)。

我正在尝试将“源”值与“目标”值相匹配。

所以我已经有了源名称,但现在我正在使用大量的字符串解析来匹配这两者。如何使用 Regex 实现相同的目标?

编辑:似乎有些混乱。

"Travis - Sing" 是我的源字符串,我正在尝试将其匹配到:

"Travis - Sing (2001).mp3"
"Travis - Sing (Edit).mp3"
"Travis - Sing (New Edit).mp3"

EDIT2:删除了括号。

【问题讨论】:

  • 我真的不明白你想要什么。你有没有像“Travis - Sing Travis - Sing (2001).mp3”这样的字符串,并且你想拉出:source="Travis - Sing" target="Travis - Sing (2001).mp3" 或者你有一个像“Travis - Sing”这样的几个源字符串,你想匹配一堆文件名吗?还是我不太了解的其他东西?
  • 你提到的最后一个。我认为我在“代码”底部的信息会很明显。

标签: c# .net regex


【解决方案1】:

您似乎正在寻找以某个字符串开头的所有文件 - 这将回答您的所有示例。这可以很容易地实现,无需使用两个循环或使用 linq 的正则表达式:

var matches = from source in sources
              select new
                      {
                          Source = source,
                          Targets = from file in targets
                                    where file.StartsWith(source)
                                    select file
                      };

您也可以使用正则表达式代替 StartsWith 条件,例如:

where Regex.IsMatch(file, String.Format("^{0}", source), RegexOptions.IgnoreCase)

这可能可以通过多种方式进行优化,但 Andrew 建议编写一个长模式,动态完成时不会更快。

【讨论】:

  • +1 我实际上并不建议按照我的方式去做,我会用类似于你正在做的事情来做。我的回答更多是为了清除他的正则表达式查询。
  • 谢谢,我确实使用了这个。只是认为正则表达式会更快,这就是我问的原因。我想我应该坚持我的旧方法。
【解决方案2】:

从您对我的评论的回答来看,我很确定您正在寻找像这样简单的东西。

因此您可以使用“|”分隔多个搜索词。这是alternation construct.

class Program
{
    private static List<string> searchList = new List<string>
                                     {
                                         "Travis - Sing (2001).mp3",
                                         "Travis - Sing (Edit).mp3",
                                         "Mission Impossible I - Main Theme.mp3",
                                         "Mission Impossible II - Main Theme.mp3",
                                         "doesn't match"
                                     };

    static void Main(string[] args)
    {
        var matchRegex = new Regex("Travis - Sing|Mission Impossible I");
        var matchingStrings = searchList.Where(str => matchRegex.IsMatch(str));

        foreach (var str in matchingStrings)
        {
            Console.WriteLine(str);
        }
    }
}

编辑 想知道自己匹配的是什么,可以加groups

    static void Main(string[] args)
    {
        var matchRegex = new Regex("(?<travis>Travis - Sing)|(?<mi>Mission Impossible I)");

        foreach (var str in searchList)
        {
            var match = matchRegex.Match(str);
            if (match.Success)
            {
                if (match.Groups["travis"].Success)
                {
                    Console.WriteLine(String.Format("{0} matches against travis", str));
                }
                else if (match.Groups["mi"].Success)
                {
                    Console.WriteLine(String.Format("{0} matches against mi", str));
                }
            }
        }
    }

【讨论】:

  • 谢谢,我想是这样。我有 2 个问题。您是否在源列表中包含括号,而不是搜索列表?如果是这样,他们应该出去。抱歉,我认为在问题中将它们分开会很清楚。第二个问题是,是否 |意味着正则表达式中的单独条目?如果是这样,那么我应该创建一个字符串?基本上我想收集每个源字符串的匹配项。所以就像 source0 -> a, b, c | source1 -> d, e...
  • 在我的回答中添加了更多信息。
  • 谢谢。有没有办法在不创建很长的单个字符串的情况下将组添加到正则表达式?所以就像 regex.AddGroup("travis"), ...
  • 好吧,因为“非常长的单个字符串”实际上只是一遍又一遍地重复的相同格式,您可以将它们构造为单独的字符串,然后使用 String.Join() 将它们连接在一起与 |之间的字符。
【解决方案3】:

源和目标之间总是有多个空格吗?如果是这样,那么以下将匹配:

/^(.*?)\s{2,}(.*?)$/

它基本上匹配两个项目,一个在任何 2+ 空格的间隙之前,一个在那个间隙之后。 (捕获模式使用非贪婪的.*?,因此如果有超过 2 个空格,额外的空格也不会被捕获。)

【讨论】:

  • 谢谢。一些源字符串没有任何空格。我应该更新帖子。
  • 空格 in 源无关紧要 - 我的问题是关于源和目标之间是否总是有多个空格 。即它总是(source)XX(target) 还是在某些情况下它只有一个空格(source)X(target) 其中X 是一个空格字符?
  • 对不起。我的意思是它们是单独的字符串,我想将源与目标匹配,所以“Travis - Sing”是我的源,第 1、2 和 3 行是我想要匹配的,因为它们是相同的歌曲。我的意思是第 1、2 和 3 行 (Travis - Sing (2001).mp3) ... 等
【解决方案4】:

下面的方法更健壮一些(允许在源和目标之间使用不同数量的空格或连字符)。例如。 target 可能在单词之间有多余的空格,但它仍然会匹配。

首先确定字符串中允许作为单词分隔符的字符。然后使用分隔符将源字符串和目标字符串拆分为标记。然后检查是否找到源中的单词作为开头单词。

例如(Java) 我使用空格和连字符作为分隔符

public boolean isValidMatch(String source, String target){
    String[] sourceTokens = source.split("[\\s\\-]+");  // split on sequence of 
    //whitespaces or dashes. Two dashes between words will still split 
    //same as one dash.

    String[] targetTokens = target.split("[\\s\\-]+"); // split similarly
    if(sourceTokens.length>targetTokens.length){
        return false;
    }

    for(int i=0;i<souceTokens.length;i++){
        if(!sourceTokens[i].equals(targetTokens[i])){
            return false;
        }
    }
    return true;
}

PS:您可能需要添加点 '.'字符作为分隔符,以防您有源“Hello World”和目标“Hello World.mp3”;目前它不会匹配,因为正则表达式不会在点上拆分,但如果您扩展分隔符集以包含点,那么它会。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-01-16
    • 2019-05-01
    • 2013-10-18
    • 2022-01-17
    • 1970-01-01
    • 2011-05-06
    • 2014-01-16
    • 1970-01-01
    相关资源
    最近更新 更多