Как разобрать таблицу Lua со странной структурой с помощью C#?

Я хотел бы проанализировать файл, который содержит только таблицу, которая была сохранена с помощью Lua, однако, хотя информация логична (легко понять, для чего она нужна), концепция хранения очень затрудняет использование обычных стратегий разбора Lua.

Например, это фрагмент одной части конструкции:

["Bag-3"] = {
    ["ids"] = {
        2589, -- [1]
        108996, -- [2]
        4306, -- [3]
        2453, -- [4]
        108330, -- [5]
        2450, -- [6]
        4337, -- [7]
        2592, -- [8]
        108326, -- [9]
        6470, -- [10]
        1529, -- [11]
        4338, -- [12]
        3404, -- [13]
        3685, -- [14]
        108325, -- [15]
        108324, -- [16]
        7067, -- [17]
        785, -- [18]
        5503, -- [19]
        5504, -- [20]
        7069, -- [21]
        5500, -- [22]
        108323, -- [23]
        12662, -- [24]
        53010, -- [25]
        62791, -- [26]
        76061, -- [27]
        74866, -- [28]
        120945, -- [29]
        109131, -- [30]
        111557, -- [31]
        30817, -- [32]
        89112, -- [33]
        30183, -- [34]
        23572, -- [35]
        36931, -- [36]
        34057, -- [37]
        43102, -- [38]
        74249, -- [39]
        72120, -- [40]
        79010, -- [41]
        72092, -- [42]
        72094, -- [43]
        72103, -- [44]
        102542, -- [45]
        102543, -- [46]
        102541, -- [47]
        72163, -- [48]
        36925, -- [49]
        36919, -- [50]
        36928, -- [51]
        36934, -- [52]
        21877, -- [53]
        12205, -- [54]
        10285, -- [55]
        3356, -- [56]
        [97] = 72988,
        [95] = 82441,
        [96] = 72988,
        [98] = 72988,
    },
    ["links"] = {
        "|cffffffff|Hitem:2589:0:0:0:0:0:0:0:100:264:0:0:0|h[Linen Cloth]|h|r", -- [1]
        "|cff1eff00|Hitem:108996:0:0:0:0:0:0:0:100:264:0:0:0|h[Alchemical Catalyst]|h|r", -- [2]
        "|cffffffff|Hitem:4306:0:0:0:0:0:0:0:100:264:0:0:0|h[Silk Cloth]|h|r", -- [3]
        "|cffffffff|Hitem:2453:0:0:0:0:0:0:0:100:264:0:0:0|h[Bruiseweed]|h|r", -- [4]
        "|cffffffff|Hitem:108330:0:0:0:0:0:0:0:100:264:0:0:0|h[Stranglekelp Blade]|h|r", -- [5]
        "|cffffffff|Hitem:2450:0:0:0:0:0:0:0:100:264:0:0:0|h[Briarthorn]|h|r", -- [6]
        "|cffffffff|Hitem:4337:0:0:0:0:0:0:0:100:264:0:0:0|h[Thick Spider's Silk]|h|r", -- [7]
        "|cffffffff|Hitem:2592:0:0:0:0:0:0:0:100:264:0:0:0|h[Wool Cloth]|h|r", -- [8]
        "|cffffffff|Hitem:108326:0:0:0:0:0:0:0:100:264:0:0:0|h[Khadgar's Whisker Stem]|h|r", -- [9]
        "|cffffffff|Hitem:6470:0:0:0:0:0:0:0:100:264:0:0:0|h[Deviate Scale]|h|r", -- [10]
        "|cff1eff00|Hitem:1529:0:0:0:0:0:0:0:100:264:0:0:0|h[Jade]|h|r", -- [11]
        "|cffffffff|Hitem:4338:0:0:0:0:0:0:0:100:264:0:0:0|h[Mageweave Cloth]|h|r", -- [12]
        "|cffffffff|Hitem:3404:0:0:0:0:0:0:0:100:264:0:0:0|h[Buzzard Wing]|h|r", -- [13]
        "|cffffffff|Hitem:3685:0:0:0:0:0:0:0:100:264:0:0:0|h[Raptor Egg]|h|r", -- [14]
        "|cffffffff|Hitem:108325:0:0:0:0:0:0:0:100:264:0:0:0|h[Liferoot Stem]|h|r", -- [15]
        "|cffffffff|Hitem:108324:0:0:0:0:0:0:0:100:264:0:0:0|h[Kingsblood Petal]|h|r", -- [16]
        "|cffffffff|Hitem:7067:0:0:0:0:0:0:0:100:264:0:0:0|h[Elemental Earth]|h|r", -- [17]
        "|cffffffff|Hitem:785:0:0:0:0:0:0:0:100:264:0:0:0|h[Mageroyal]|h|r", -- [18]
        "|cffffffff|Hitem:5503:0:0:0:0:0:0:0:100:264:0:0:0|h[Clam Meat]|h|r", -- [19]
        "|cffffffff|Hitem:5504:0:0:0:0:0:0:0:100:264:0:0:0|h[Tangy Clam Meat]|h|r", -- [20]
        "|cffffffff|Hitem:7069:0:0:0:0:0:0:0:100:264:0:0:0|h[Elemental Air]|h|r", -- [21]
        "|cff1eff00|Hitem:5500:0:0:0:0:0:0:0:100:264:0:0:0|h[Iridescent Pearl]|h|r", -- [22]
        "|cffffffff|Hitem:108323:0:0:0:0:0:0:0:100:264:0:0:0|h[Wild Steelbloom Petal]|h|r", -- [23]
        "|cff1eff00|Hitem:12662:0:0:0:0:0:0:0:100:264:0:0:0|h[Demonic Rune]|h|r", -- [24]
        "|cffffffff|Hitem:53010:0:0:0:0:0:0:0:100:264:0:0:0|h[Embersilk Cloth]|h|r", -- [25]
        "|cffffffff|Hitem:62791:0:0:0:0:0:0:0:100:264:0:0:0|h[Blood Shrimp]|h|r", -- [26]
        "|cff0070dd|Hitem:76061:0:0:0:0:0:0:0:100:264:0:0:0|h[Spirit of Harmony]|h|r", -- [27]
        "|cffffffff|Hitem:74866:0:0:0:0:0:0:0:100:264:0:0:0|h[Golden Carp]|h|r", -- [28]
        "|cff1eff00|Hitem:120945:0:0:0:0:0:0:0:100:264:0:0:0|h[Primal Spirit]|h|r", -- [29]
        "|cffffffff|Hitem:109131:0:0:0:0:0:0:0:100:264:0:0:0|h[Raw Clefthoof Meat]|h|r", -- [30]
        "|cffffffff|Hitem:111557:0:0:0:0:0:0:0:100:264:0:0:0|h[Sumptuous Fur]|h|r", -- [31]
        "|cffffffff|Hitem:30817:0:0:0:0:0:0:0:100:264:0:0:0|h[Simple Flour]|h|r", -- [32]
        "|cffffffff|Hitem:89112:0:0:0:0:0:0:0:100:264:0:0:0|h[Mote of Harmony]|h|r", -- [33]
        "|cffa335ee|Hitem:30183:0:0:0:0:0:0:0:100:264:0:0:0|h[Nether Vortex]|h|r", -- [34]
        "|cff0070dd|Hitem:23572:0:0:0:0:0:0:0:100:264:0:0:0|h[Primal Nether]|h|r", -- [35]
        "|cffa335ee|Hitem:36931:0:0:0:0:0:0:0:100:264:0:0:0|h[Ametrine]|h|r", -- [36]
        "|cffa335ee|Hitem:34057:0:0:0:0:0:0:0:100:264:0:0:0|h[Abyss Crystal]|h|r", -- [37]
        "|cff0070dd|Hitem:43102:0:0:0:0:0:0:0:100:264:0:0:0|h[Frozen Orb]|h|r", -- [38]
        "|cffffffff|Hitem:74249:0:0:0:0:0:0:0:100:264:0:0:0|h[Spirit Dust]|h|r", -- [39]
        "|cffffffff|Hitem:72120:0:0:0:0:0:0:0:100:264:0:0:0|h[Exotic Leather]|h|r", -- [40]
        "|cffffffff|Hitem:79010:0:0:0:0:0:0:0:100:264:0:0:0|h[Snow Lily]|h|r", -- [41]
        "|cffffffff|Hitem:72092:0:0:0:0:0:0:0:100:264:0:0:0|h[Ghost Iron Ore]|h|r", -- [42]
        "|cff1eff00|Hitem:72094:0:0:0:0:0:0:0:100:264:0:0:0|h[Black Trillium Ore]|h|r", -- [43]
        "|cff1eff00|Hitem:72103:0:0:0:0:0:0:0:100:264:0:0:0|h[White Trillium Ore]|h|r", -- [44]
        "|cff1eff00|Hitem:102542:0:0:0:0:0:0:0:100:264:0:0:0|h[Ancient Pandaren Spices]|h|r", -- [45]
        "|cff1eff00|Hitem:102543:0:0:0:0:0:0:0:100:264:0:0:0|h[Aged Mogu'shan Cheese]|h|r", -- [46]
        "|cff1eff00|Hitem:102541:0:0:0:0:0:0:0:100:264:0:0:0|h[Aged Balsamic Vinegar]|h|r", -- [47]
        "|cff0070dd|Hitem:72163:0:0:0:0:0:0:0:100:264:0:0:0|h[Magnificent Hide]|h|r", -- [48]
        "|cffa335ee|Hitem:36925:0:0:0:0:0:0:0:100:264:0:0:0|h[Majestic Zircon]|h|r", -- [49]
        "|cffa335ee|Hitem:36919:0:0:0:0:0:0:0:100:264:0:0:0|h[Cardinal Ruby]|h|r", -- [50]
        "|cffa335ee|Hitem:36928:0:0:0:0:0:0:0:100:264:0:0:0|h[Dreadstone]|h|r", -- [51]
        "|cffa335ee|Hitem:36934:0:0:0:0:0:0:0:100:264:0:0:0|h[Eye of Zul]|h|r", -- [52]
        "|cffffffff|Hitem:21877:0:0:0:0:0:0:0:100:264:0:0:0|h[Netherweave Cloth]|h|r", -- [53]
        "|cffffffff|Hitem:12205:0:0:0:0:0:0:0:100:264:0:0:0|h[White Spider Meat]|h|r", -- [54]
        "|cffffffff|Hitem:10285:0:0:0:0:0:0:0:100:264:0:0:0|h[Shadow Silk]|h|r", -- [55]
        "|cffffffff|Hitem:3356:0:0:0:0:0:0:0:100:264:0:0:0|h[Kingsblood]|h|r", -- [56]
        [97] = "|cffffffff|Hitem:72988:0:0:0:0:0:0:0:100:264:0:0:0|h[Windwool Cloth]|h|r",
        [95] = "|cffffffff|Hitem:82441:0:0:0:0:0:0:0:100:264:0:0:0|h[Bolt of Windwool Cloth]|h|r",
        [96] = "|cffffffff|Hitem:72988:0:0:0:0:0:0:0:100:264:0:0:0|h[Windwool Cloth]|h|r",
        [98] = "|cffffffff|Hitem:72988:0:0:0:0:0:0:0:100:264:0:0:0|h[Windwool Cloth]|h|r",
    },
    ["counts"] = {
        51, -- [1]
        5, -- [2]
        76, -- [3]
        9, -- [4]
        10, -- [5]
        8, -- [6]
        2, -- [7]
        28, -- [8]
        41, -- [9]
        nil, -- [10]
        nil, -- [11]
        nil, -- [12]
        5, -- [13]
        5, -- [14]
        28, -- [15]
        76, -- [16]
        nil, -- [17]
        3, -- [18]
        10, -- [19]
        8, -- [20]
        2, -- [21]
        nil, -- [22]
        53, -- [23]
        nil, -- [24]
        8, -- [25]
        5, -- [26]
        nil, -- [27]
        10, -- [28]
        16, -- [29]
        nil, -- [30]
        nil, -- [31]
        20, -- [32]
        128, -- [33]
        9, -- [34]
        nil, -- [35]
        2, -- [36]
        nil, -- [37]
        nil, -- [38]
        40, -- [39]
        148, -- [40]
        20, -- [41]
        46, -- [42]
        45, -- [43]
        23, -- [44]
        18, -- [45]
        5, -- [46]
        8, -- [47]
        2, -- [48]
        nil, -- [49]
        nil, -- [50]
        2, -- [51]
        nil, -- [52]
        30, -- [53]
        14, -- [54]
        nil, -- [55]
        3, -- [56]
        [97] = 200,
        [95] = 2,
        [98] = 200,
    },
    ["size"] = 98,
},

Если вы заметили, особенно под счетчиками, все, кроме трех нижних, являются количеством предметов в этом конкретном слоте сумки (это сохраненные данные из дополнения Warcraft datastore_containers). Однако последние три в списке (и это варьируется) имеют такой формат:

[bag slot #] = count

Как я могу разумно пройти по этому дереву, поскольку важны как номер слота (например, из индекса, за исключением последних трех (иногда это последние 10, последние четыре и т. Д.), И количество элементов.

В идеале я хотел бы использовать что-то, исходный код которого я могу напрямую встроить в свой проект, а не добавлять в дистрибутив еще одну предварительно скомпилированную библиотеку.


person Kraang Prime    schedule 09.07.2016    source источник


Ответы (1)


На самом деле это просто проблема правильного разбора таблицы. Может быть некоторая путаница только из-за того, как выложена таблица, разбивка должна быть немного легче для чтения:

["Bag-3"] = {
    ["ids"] = {
        2589, -- [1]
        ...
        3356, -- [56]
        [97] = 72988,
        [95] = 82441,
    },
    ["links"] = {
        "|cffffffff|Hitem:2589:0:0:0:0:0:0:0:100:264:0:0:0|h[Linen Cloth]|h|r", -- [1]
        ...
        "|cffffffff|Hitem:3356:0:0:0:0:0:0:0:100:264:0:0:0|h[Kingsblood]|h|r", -- [56]
        [97] = "|cffffffff|Hitem:72988:0:0:0:0:0:0:0:100:264:0:0:0|h[Windwool Cloth]|h|r",
        [95] = "|cffffffff|Hitem:82441:0:0:0:0:0:0:0:100:264:0:0:0|h[Bolt of Windwool Cloth]|h|r",
    },
    ["counts"] = {
        51, -- [1]
        ...
        3, -- [56]
        [97] = 200,
        [95] = 2,
    },
    ["size"] = 98,
},

Во-первых, комментарий в Lua помечен --, поэтому строки, заканчивающиеся на -- [X], являются просто комментариями, обозначающими, что [X] — это конкретный индекс (в n+1) в массиве, а значение перед , — это значение по этому индексу в массиве. множество.

Поэтому, если с индексом не связано никакого значения, его значение по умолчанию будет равно null (или nil в Lua). Строки, которые не имеют комментариев и явно указывают индекс (например, [97] = 72988,), являются явными сеттерами.

Таблица сохраняется таким образом, что конгруэнтные значения имеют свой индекс в виде комментариев (нет необходимости явно указывать индекс), и, поскольку конгруэнтные значения таблицы заканчиваются на 56 (в этом примере), то любые значения после должны быть явно указаны и назначены, что вот почему вы увидите что-то вроде 3356, -- [56], за которым следует [97] = 72988,; значение для [97] должно быть установлено явно, так как между ним и [56] ничего нет, а также почему вы увидите некоторые значения не по порядку.

Если каждая «сумка» будет иметь один и тот же макет (не обязательно одинаковые значения, но один и тот же макет «таблицы»), вы можете проанализировать это с помощью класса (нет необходимости во внешних библиотеках), сделав примечание, чтобы убедиться, что свойство ["size"] используется , пример:

class Bag
{
    public string Name = string.Empty;
    public int Size = 0;

    public List<int?> Counts = new List<int?>();
    public List<int?> IDs = new List<int?>();
    public List<string> Links = new List<string>();

    public Bag() { }

    public static Bag Parse(string input)
    {
        Bag bag = new Bag();
        int? iv = null;
        int idx = input.IndexOf("[\"") + 2;
        bag.Name = input.Substring(idx, input.IndexOf("\"]") - idx);
        idx = input.IndexOf("[\"size\"] = ") + "[\"size\"] = ".Length; // len;
        bag.Size = int.Parse(input.Substring(idx, input.Substring(idx).IndexOf(",")));

        foreach (object val in GetVals("ids", input, bag.Size)) {
            iv = null;
            if (val != null && val.ToString() != "nil") {
                iv = int.Parse(val.ToString());
            }
            bag.IDs.Add(iv);
        }

        foreach (object val in GetVals("links", input, bag.Size)) {
            bag.Links.Add((string)val);
        }

        foreach (object val in GetVals("counts", input, bag.Size)) {
            iv = null;
            if (val != null && val.ToString() != "nil") {
                iv = int.Parse(val.ToString());
            }
            bag.Counts.Add(iv);
        }
        return bag;
    }

    private static List<object> GetVals(string id, string input, int size)
    {
        List<object> list = new List<object>();
        for (int i = 0; i < size; ++i) { list.Add(null); }
        string tmp, ival = string.Format("[\"{0}\"] = {{", id);
        string[] tsplit = null;
        int len = ival.Length;
        int idx = input.IndexOf(ival) + len;
        foreach (string val in input.Substring(idx, input.Substring(idx).IndexOf("}")).Split('\n')) {
            tmp = val.Trim();
            if (string.IsNullOrEmpty(tmp)) { continue; }
            tsplit = tmp.Split(new string[] { "," }, StringSplitOptions.RemoveEmptyEntries);
            if (tsplit.Length == 2) {
                int i = (int.Parse((((tsplit[1].Replace("-", "")).Replace("[", "")).Replace("]", "")).Trim()) - 1);
                list[i] = tsplit[0].Trim();
            } else {
                int i = (int.Parse((tsplit[0].Substring(0, tsplit[0].IndexOf("=")).Replace("[", "")).Replace("]", "").Trim()) - 1);
                list[i] = tsplit[0].Substring(tsplit[0].IndexOf("=") + 1).Trim();
            }
        }
        return list;
    }
}

Затем использовать: Bag b = Bag.Parse(bagTableValue);

Это более упрощенный пример, и вы можете использовать другие методы (например, RegEx), но он больше иллюстрирует, как анализировать таблицу.

Надеюсь, что это может помочь.

person txtechhelp    schedule 09.07.2016