繁体   English   中英

正则表达式模式匹配多组 C#

[英]Regex pattern matching with multiple groups C#

我有一个类似于以下内容的文件:

background_color{ 104, 184, 104 }

tile_pattern{
  id = "1",
  ground = "empty",
  default_layer = 2,
  x = 0,
  y = 0,
  width = 8,
  height = 16,
  repeat_mode = "none",
}

tile_pattern{
  id = "999",
  ground = "traversable",
  default_layer = 0,
  x = 40,
  y = 1000,
  width = 8,
  height = 8,
}

tile_pattern{
  id = "abyss_bridge",
  ground = "traversable",
  default_layer = 0,
  x = 280,
  y = 448,
  width = 16,
  height = 16,
}

tile_pattern{
  id = "acid",
  ground = "prickles",
  default_layer = 0,
  x = { 712, 728, 744 },
  y = { 384, 384, 384 },
  width = 16,
  height = 16,
}

tile_pattern{
  id = "lava",
  ground = "lava",
  default_layer = 0,
  x = { 696, 696, 696, 696 },
  y = { 368, 384, 400, 384 },
  width = 16,
  height = 16,
}

tile_pattern{
  id = "hole_parallax.1-1",
  ground = "hole",
  default_layer = 0,
  x = 312,
  y = 224,
  width = 16,
  height = 16,
  scrolling = "self",
}

tile_pattern{
  id = "air_duct.1",
  ground = "wall",
  default_layer = 0,
  x = 880,
  y = 48,
  width = 32,
  height = 24,
  repeat_mode = "none",
}

border_set{
  id = "wall_hole",
  inner = true,
  pattern_0 = "wall_hole.4-1",
  pattern_1 = "wall_hole.1-1",
  pattern_2 = "wall_hole.3-1",
  pattern_3 = "wall_hole.2-1",
  pattern_4 = "wall_hole.corner.2-1",
  pattern_5 = "wall_hole.corner.1-1",
  pattern_6 = "wall_hole.corner.3-1",
  pattern_7 = "wall_hole.corner.4-1",
  pattern_8 = "wall_hole.corner_reverse.2-1",
  pattern_9 = "wall_hole.corner_reverse.1-1",
  pattern_10 = "wall_hole.corner_reverse.3-1",
  pattern_11 = "wall_hole.corner_reverse.4-1",
}

border_set{
  id = "wall_low-1",
  pattern_0 = "wall_low.4-1",
  pattern_1 = "wall_low.1-1",
  pattern_2 = "wall_low.3-1",
  pattern_3 = "wall_low.2-1",
  pattern_4 = "wall_low.corner.2-1",
  pattern_5 = "wall_low.corner.1-1",
  pattern_6 = "wall_low.corner.3-1",
  pattern_7 = "wall_low.corner.4-1",
  pattern_8 = "wall_low.corner_reverse.2-1b",
  pattern_9 = "wall_low.corner_reverse.1-1b",
  pattern_10 = "wall_low.corner_reverse.3-1b",
  pattern_11 = "wall_low.corner_reverse.4-1b",
}

我将它加载到一个名为datString的字符串中。 我正在尝试匹配单个正则表达式中的所有tile_pattern部分。

这是我到目前为止所拥有的:

//tilePatterns = new List<TilePatternData>();
        //tile_pattern{
        //id = "10", (string)
        //ground = "empty", (string)
        //default_layer = 2, (number)
        //(x = 72,) (x = { 712, 728, 744 },) (number or table)(only matching the number, have to add in the table)
        //(y = 0,) (y = { 384, 384, 384 },) (number or table)(only matching the number, have to add in the table)
        //width = 8,
        //height = 16,
        //frame_delay(number, optional)(None in test file)
        //mirror_loop (boolean, optional)(None in test file)
        //scrolling (string, optional)(The Ones in the test file do not have a repeat_mode
        //repeat_mode = "none", (string, optional)
        //}
        parts = new Regex("tile_pattern\\s*{\\s*(id\\s*=\\s*\".+\",\\s*ground\\s*=\\s*\".+\",\\s*default_layer\\s*=\\s*-*\\d+,\\s*x\\s*=\\s*\\d+,\\s*y\\s*=\\s*\\d+,\\s*width\\s*=\\s*\\d+,\\s*height\\s*=\\s*\\d+,\\s*\\w*\\s*=*\\s*\"*\\w*\"*),*\\s*}");
        match = parts.Match(datFileString);
        Debug.Log("Match " + match.Success + " : " + match.Length);
        while (match.Success)
        {
            // To easily see which ones are getting loaded in
            Debug.Log(match.Groups[1]);

            //TilePatternData tilePatternData = new TilePatternData();
            //tilePatternData.LoadFromDatFile(match.Groups[1].ToString());
            //tilePatterns.Add(tilePatternData);

            match = match.NextMatch();
        }

通过我的调试日志一目了然地返回匹配长度 138(应该是 4830)似乎唯一缺少的是具有 x = { 712, 728, 744 } 的 32 个模式,我还没有弄清楚如何将此添加到我的捕获组中,但我们将不胜感激。 另外,我将如何添加 3 个可选字段以确保它们是否都匹配?

需要添加到图案

tile_pattern{
  id = "acid",
  ground = "prickles",
  default_layer = 0,
  x = { 712, 728, 744 },
  y = { 384, 384, 384 },
  width = 16,
  height = 16,
}

您的文件输入似乎来自 Solarus Quest Tileset 数据文件。 根据规格

瓦片集数据文件的这种语法实际上是有效的 Lua。

考虑使用 Lua 解析器,而不是使用正则表达式。 NLua似乎可以用 Lua 做很多事情,尽管它对于解析变量列表表示法可能有点多。

另请参阅:在 C# /.Net 中解析 Lua 数据结构的最简单方法

你的正则表达式真的比它必须的复杂得多......现在只有你和上帝知道它做了什么 - 一周后只有上帝会;-)

试试这个正则表达式: tile_pattern\{(?:[^{}]|(?R))+\}

还请确保设置正确的标志(因为我不知道 C# 的语法)

  • 全局(第一次匹配后不返回)
  • 扩展(忽略空格)

另请参阅此示例https://regex101.com/r/zqcOBY/1

这还负责过滤文件中未来的新元素,而无需您在正则表达式中定义的明确排除规则。

我采用了不同的解决方案

string[] patternString = Regex.Split(datFileString, "tile_pattern{");
            string[] borderString = Regex.Split(patternString[patternString.Length - 1], "border_set{");
            patternString[patternString.Length - 1] =
                patternString[patternString.Length - 1]
                    .Remove(patternString[patternString.Length - 1].IndexOf("border_set{", StringComparison.Ordinal));
            tilePatterns = new List<TilePatternData>();

            foreach (string s in patternString)
            {
                if (s.Contains("background_color")) continue;

                TilePatternData tilePatternData = new TilePatternData();
                tilePatternData.LoadFromDatFile(s);
                tilePatterns.Add(tilePatternData);
            }

然后在 TilePatternData class

public void LoadFromDatFile(string datFileString)
        {
            //tile_pattern{
            //id = "10", (string)
            //ground = "empty", (string)
            //default_layer = 2, (number)
            //(x = 72,) (x = { 712, 728, 744 },) (number or table)(only matching the number, have to add in the table)
            //(y = 0,) (y = { 384, 384, 384 },) (number or table)(only matching the number, have to add in the table)
            //width = 8,
            //height = 16,
            //frame_delay = 250 (number, optional)
            //mirror_loop = true (boolean, optional)
            //scrolling (string, optional)(The Ones in the test file do not have a repeat_mode
            //repeat_mode = "none", (string, optional)
            //}

            Regex parts = new Regex("\\s*(\\w+)\\s*=\\s*\"(\\w+)\"");
            Match match = parts.Match(datFileString);
            //Debug.Log(match.Success + " " + datFileString);
            while (match.Success)
            {
                string pram = match.Groups[1].ToString();
                string value = match.Groups[2].ToString();
                // Debug.Log(pram + "=" + value);
                switch (pram)
                {
                    case "id":
                        id = value;
                        break;
                    case "ground":
                        Enum.TryParse(value, out ground);
                        break;
                    case "scrolling":
                        Debug.Log(pram + "=" + value);
                        Enum.TryParse(value, out scrollingEffect);
                        break;
                    case "repeat_mode":
                        Enum.TryParse(value, out repeatMode);
                        break;
                }

                match = match.NextMatch();
            }

            parts = new Regex("\\s*(\\w+)\\s*=\\s*(-*\\d+)");
            match = parts.Match(datFileString);
            // Debug.Log(match.Success + ": \\s*(\\w+)\\s*=\\s*(-*\\d+)");
            while (match.Success)
            {
                string pram = match.Groups[1].ToString();
                string value = match.Groups[2].ToString();
                // Debug.Log(pram + "=" + value);
                switch (pram)
                {
                    case "x":
                        int.TryParse(value, out startX);
                        break;
                    case "y":
                        int.TryParse(value, out startY);
                        break;
                    case "width":
                        int.TryParse(value, out width);
                        break;
                    case "height":
                        int.TryParse(value, out height);
                        break;
                    case "default_layer":
                        int.TryParse(value, out defaultLayer);
                        break;
                    case "frame_delay":
                        int.TryParse(value, out height);
                        break;
                }

                match = match.NextMatch();
            }

            // x = { 712, 728, 744 },
            parts = new Regex("\\s*([xy])\\s*=\\s*{(\\s*\\d+,*)*\\s*}");
            match = parts.Match(datFileString);
            Debug.Log(match.Success + ": \\s*([xy])\\s*=\\s*{(\\s*\\d+,*)*\\s*}");
            while (match.Success)
            {
                Debug.Log(match.Groups[2].Captures.Count);
                string pram = match.Groups[1].ToString();
                string[] value = new string[match.Groups[2].Captures.Count];
                // work in progress to extract the table values
            }

            parts = new Regex("\\s*mirror_loop\\s*=\\s*(\\w+)");
            match = parts.Match(datFileString);
            //Debug.Log(match.Success + ": \\s*mirror_loop\\s*=\\s*(\\w+)");
            if (!match.Success) return;
            bool.TryParse(match.Groups[1].ToString(), out mirrorLoop);
            Debug.Log(mirrorLoop);
        }

可能还有一种方法可以进一步简化这一点。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM