Search code examples
lua

Using a single pattern to capture multiple values containing in a file in lua script


i have a text file that contains data in the format YEAR, CITY, COUNTRY. data is written as one YEAR, CITY, COUNTRY per line. eg -:

  • 1896, Athens, Greece
  • 1900, Paris, France

Previously i was using the data hard coded like this

local data = {} 

data[1] = { year = 1896, city = "Athens", country = "Greece" }
data[2] = { year = 1900, city = "Paris", country = "France" }
data[3] = { year = 1904, city = "St Louis", country = "USA" }
data[4] = { year = 1908, city = "London", country = "UK" }
data[5] = { year = 1912, city = "Stockholm", country = "Sweden" }
data[6] = { year = 1920, city = "Antwerp", country = "Netherlands" }

Now i need to read the lines from the file and get the values in to the private knowledge base "local data = {} "

Cant figure out how to capture multiple values using a single pattern from the data in the file.

My code so far is

local path = system.pathForFile( "olympicData.txt", system.ResourceDirectory )
 
-- Open the file handle
local file, errorString = io.open( path, "r" )
 
if not file then
    -- Error occurred; output the cause
    print( "File error: " .. errorString )
else
    -- Read each line of the file
    for line in file:lines() do
        local i, value = line:match("%d")
        table.insert(data, i)
        
    -- Close the file
    io.close(file)
    
end
 
file = nil

Solution

  • Given that you read a line like

    1896, Athens, Greece
    

    You can simply obtain the desired values using captures.

    https://www.lua.org/manual/5.3/manual.html#6.4.1

    Captures: A pattern can contain sub-patterns enclosed in parentheses; they describe captures. When a match succeeds, the substrings of the subject string that match captures are stored (captured) for future use. Captures are numbered according to their left parentheses. For instance, in the pattern "(a*(.)%w(%s*))", the part of the string matching "a*(.)%w(%s*)" is stored as the first capture (and therefore has number 1); the character matching "." is captured with number 2, and the part matching "%s*" has number 3.

    As a special case, the empty capture () captures the current string position (a number). For instance, if we apply the pattern "()aa()" on the string "flaaap", there will be two captures: 3 and 5.

    local example = "1896, Athens, Greece"
    local year, city, country = example:match("(%d+), (%w+), (%w+)")
    print(year, city, country)