String patterns: Allow numbers and hyphens?

I’m currently trying to restrict the content of a TextBox to signed integers only; I’m part of the way there already, using string.gsub to remove anything that isn’t a numerical character, but there’s a hitch. I’m relying on inverted character classes to do this - %D, specifically, to select anything that isn’t a digit. This does not permit hyphens, which does not allow signed integers to be typed into the text field.

As far as I can tell, there isn’t any way to invert %- to also permit hyphens, and there isn’t an inverted gsub function that replaces everything except what I pass as a pattern. Is there some other way to permit both numbers and hyphens, whilst leaving out all other characters? I’d prefer it as a whitelist, for brevity’s sake.

To accomplish this with a whitelist, you can iterate through the chars in the string you are working with. Here are some examples to get you started:

-- Returns true if a string contains any of the chars in a given table.
-- @string the string you want to check
-- @char_list a list of characters that you want to search for in the string
-- @char_list would look like {"a", "b", "c"}
local function StringHasChars(string, char_list)
    local result = false
    -- Turns the string into a table of chars and iterates through each char
    for index, letter in ipairs(string:split("")) do
        -- Check each character in the string against each character in your list
        for index, letter_to_check in pairs(char_list) do
            if (letter == letter_to_check) then
                return true
            end
        end
    end
    
    return result
end

You could also filter chars out of the string in a similar way:

-- Returns the original string without the chars you specify in the char_list.
-- @string the string you want to check
-- @char_list a list of characters that you want to remove from the string
-- @char_list would look like {"a", "b", "c"}
local function FilterString(string, char_list)
    local result = ""
    -- Turns the string into a table of chars and iterates through each char
    for index, letter in ipairs(string:split("")) do
        -- Check each character in the string against each character in your list
        for index, letter_to_check in pairs(char_list) do
            if (letter ~= letter_to_check) then
                result = (result .. letter)
            end
        end
    end
    
    return result
end

You can also define your own conditions directly in this function rather than using a list of chars:

-- Returns false if the string contains anything other than numbers.
-- @string the string you want to check
local function StringIsOnlyNumbers(string)
    local result = true
    -- Turns the string into a table of chars and iterates through each char
    for index, letter in ipairs(string:split("")) do
        -- Check each character in the string against each character in your list
        for index, letter_to_check in pairs(char_list) do
            -- Put your own conditions here.
            if (type(tonumber(letter_to_check)) ~= "number") then
                return false
            end
        end
    end
    
    return result
end
1 Like