Lua string formatting on the basis of number and letter combinations

49 Views Asked by At

So I was wondering how possible it is to reformat a single string in a specific way with dashes depending on the number and letter combination positions. I'm working on a script for a game that handles license plates but it does not add dashes. I would like to format the string on the basis of numbers and letters the way License Plates are handled in the Netherlands. For example

if the license plate is 91FKTG it will format it to 91-FK-TG, if the plate is GB000T it will reformat to GB-000-T.

So the formatting would have to be done on how it detects the combination. Current combinations are

9 = number obviously, X = letter

  1. 99-XX-XX
  2. 99-XXX-9
  3. 9-XXX-99
  4. XX-999-X
  5. X-999-XX

How would I go around detecting it in LUA, and have it properly dash based on what it detects? Is it even doable?

I have no idea on how to approach this as I'm still a novice in LUA. Any help would be appreciated

3

There are 3 best solutions below

2
Mike V. On

We can apply templates to each element in the loop. The gsub function can also capture values in the template itself. This will help us. Read more here..

local function MyFormat(s)
    local x  = s:gsub("(%d%d)(%a%a)(%a%a)","%1-%2-%3")
                :gsub("(%d%d)(%a%a%a)(%d)","%1-%2-%3") 
                :gsub("(%d)(%a%a%a)(%d%d)","%1-%2-%3") 
                :gsub("(%a%a)(%d%d%d)(%a)","%1-%2-%3") 
                :gsub("(%a)(%d%d%d)(%a%a)","%1-%2-%3") 
    return x  
end

local t = { "99XXXX", "99XXX9" , "9XXX99" , "XX999X", "X999XX"}
for k, v in pairs(t) do 
    print(v,MyFormat(v))
end

results:

99XXXX    99-XX-XX
99XXX9    99-XXX-9
9XXX99    9-XXX-99
XX999X    XX-999-X
X999XX    X-999-XX

Templates will be applied to each line 5 times. If no template is found, then gsub will not change anything in the line, so the first matching template will change the line as needed

0
darkfrei On
function insertDash(str)
    str = string.gsub(str, "(%d)(%a)", "%1-%2") -- digit-letter
    str = string.gsub(str, "(%a)(%d)", "%1-%2") -- letter-digit
    str = string.gsub(str, "(%a)(%a)(%a)(%a)", "%1%2-%3%4") -- 4 letters to 2 letters and 2 letters
    return str
end

Examples:

print(insertDash("aa11")) -- aa-11
print(insertDash("11aa")) -- 11-aa
print(insertDash("123abc")) -- 123-abc
print(insertDash("abc123")) -- abc-123
print(insertDash("abcd123")) -- ab-cd-123
print(insertDash("abcd1234")) -- ab-cd-1234
0
Alexander Mashin On
local formats = {
    '99-XX-XX',
    '99-XXX-9',
    '9-XXX-99',
    'XX-999-X',
    'X-999-XX'
}

-- Convert formats to pattern => replacement pairs:
local regexes = {}
for _, mask in ipairs (formats) do
    -- Pattern operates over plate stripped of dashes:
    local pattern = mask:gsub ('[^X9]', ''):gsub ('[X9]', '(%0)'):gsub ('9', '%%d'):gsub ('X', '%%a')
    local capture = 0
    local  replacement = mask:gsub ('.', function (char)
        if char == 'X' or char == '9' then
            capture = capture + 1
            return '%' .. tostring (capture)
        else
            return char
        end
    end)
    regexes [pattern] = replacement
end

local function format (plate)
    local stripped = plate:gsub ('[^%a%d]', '')
    for pattern, replacement in pairs (regexes) do
        if stripped:match (pattern) then
            local formatted = stripped:gsub (pattern, replacement)
            return formatted
        end
    end
    return plate
end
    
local cases = {
    '12-ab-cd',
    '12abcd',
    '12a-bc-d',
    'not a plate'
}
for _, case in ipairs (cases) do
    print (case, format (case))
end