Amaterastis
Amaterastis

Reputation: 479

How to create a tables with variable length with string-like keys in lua

I have a file database. Inside that file I have something like:

DB_A = ...
DB_B = ...
.
.
.
DB_N = ...

I would like to parse the data and group them in lua code like this:

data={}

-- the result after parsing a file
 data={
    ["DB_A"] = {...},
    ["DB_B"] = {...},
    .
    .
    .
    ["DB_N"] = {...}
 }

In other words, is it possible to create a table inside a table dynamically and assign the key to each table without previously knowing what will be the names of the key (that is something I can figure out after parsing the data from a database).

Upvotes: 1

Views: 372

Answers (1)

Personage
Personage

Reputation: 484

(Just as a note, I am using Lua 5.3.5; also, I apologize that my code resembles C more than Lua!)

Iterating through your input file line-by-line--which can be done with the Lua FILE*'s lines method--you can use string.match to grab the information you are looking for from each line.

#!/usr/bin/lua

local PATTERN = "(%S+)%s?=%s?(%S+)"

local function eprintf(fmt, ...)
    io.stderr:write(string.format(fmt, ...))
    return
end

local function printf(fmt, ...)
    io.stdout:write(string.format(fmt, ...))
    return
end

local function make_table_from_file(filename)
    local input = assert(io.open(filename, "r"))
    local data = {}
    for line in input:lines() do
        local key, value = string.match(line, PATTERN)
        data[key] = value
    end
    return data
end

local function main(argc, argv)
    if (argc < 1) then
        eprintf("Filename expected from command line\n")
        os.exit(1)
    end

    local data = make_table_from_file(argv[1])
    for k, v in pairs(data) do
        printf("data[%s] = %s\n", k, data[k])
    end

    return 0
end
main(#arg, arg)

The variable declared at the top of the file, PATTERN, is your capture pattern to be used by string.match. If you are unfamiliar with how Lua's pattern matching works, this pattern looks for a series of non-space characters with zero or one spaces to its right, an equal sign, another space, and then another series of non-space characters. The two series of non-space characters are the two matches--key and value--returned by string.match in the function make_table_from_file.

The functions eprintf and printf are my Lua versions of C-style formatted output functions. The former writes to standard error, io.stderr in Lua; and the latter writes to standard output, io.stdout in Lua.

In your question, you give a sample of what your expected output is. Within your table data, you want it to contain keys that correspond to tables as values. Based on the sample input text you provided, I assume the data contained within these tables are whatever comes to the right of the equal signs in the input file--which you represent with .... As I do not know what exactly those ...s represent, I cannot give you a solid example for how to separate that right-hand data into a table. Depending on what you are looking to do, you could take the second variable returned by string.match, which I called value, and further separate it using Lua's string pattern matching. It could look something like this:

...
local function make_table_from_value(val)
    // Split `val` into distinct elements to form a table with `some_pattern`
    return {string.match(val, some_pattern)}
end

local function make_table_from_file(filename)
    local input = assert(io.open(filename, "r"))
    local data = {}
    for line in input:lines() do
        local key, value = string.match(line, PATTERN)
        data[key] = make_table_from_value(value)
    end
    return data
end
...

In make_table_from_value, string.match will return some number of elements, based on whatever string pattern you provide as its second argument, which you can then use to create a table by enclosing the function call in curly braces. It will be a table that uses numerical indices as keys--rather than strings or some other data type--starting from 1.

Upvotes: 1

Related Questions