在Lua中解析和修改数字后重构字符串

时间:2014-08-23 17:41:52

标签: string parsing random replace lua

我有类似下面的字符串(引号只显示可能有前导和尾随空格),我需要从字符串中提取数字,可以是整数或浮点数,负数或非负数。 / p>

"   M0 0.5 l 20 0 0 20.34 -20 0q10 0 10 10 t 10 10 54.333 10 h -50 z"

提取数字后,我必须将它们与随机数相乘,以下函数产生。

-- returns a random float number between the specified boundaries (floats)
function random_in_interval(lower_boundary, upper_boundary)
    return ((math.random() * (upper_boundary - lower_boundary)) + lower_boundary)
end

最后用正确的顺序重建带有字符和乘法数字的字符串。所有这一切都必须在Lua中发生,我不能使用任何外部库,因为这将在LuaTeX编译文档中使用。

不能更改字符的大小写,字符在它们之前和之后可能有也可能没有空格,但在输出中如果有的话会很好。我已经编写了一个辅助函数来添加字符前后的空格,但是当一个字符在它之前或之后有一个空格时,这将引入多个空格,这是我目前无法解决的。

-- adds whitespace before and after characters
function pad_characters(str)
    local padded_str = ""

    if #str ~= 0 then
        for i = 1, #str, 1 do
            local char = string.sub(str, i, i)

            if string.match(char, '%a') ~= nil then
                padded_str = padded_str .. " " .. char .. " "
            else
                padded_str = padded_str .. char
            end
        end
    end

    -- remove leading and trailing whitespaces
    if #padded_str ~= 0 then
        padded_str = string.match(padded_str, "^%s*(.-)%s*$")
    end

    return padded_str
end

我不知道如何解析,修改字符串的数字部分,并以正确的顺序重建它,并在纯Lua中执行此操作而不使用任何外部库。

2 个答案:

答案 0 :(得分:1)

试试这个。根据需要进行调整。

s="   M0 0.5 l 20 0 0 20.34 -20 0q10 0 10 10 t 10 10 54.333 10 h -50 z"

print(s:gsub("%S+",function (x)
    local y=tonumber(x)
    if y then
        return y*math.random()
    else
        return x
    end

end))

答案 1 :(得分:0)

我无法想出比处理每个角色更好的东西,并决定它是一个数字(数字,小数点,负号)还是其他任何东西,并按照它行事。

-- returns a random float number between the specified boundaries (floats)
function random_in_interval(lower_boundary, upper_boundary)
    return ((math.random() * (upper_boundary - lower_boundary)) + lower_boundary)
end

-- note: scaling is applied before randomization
function randomize_and_scale(str, scale_factor, lower_boundary, upper_boundary)
    local previous_was_number = false
    local processed_str = ""
    local number = ""

    for i = 1, #str, 1 do
        local char = string.sub(str, i, i)

        if previous_was_number then
            if string.match(char, '%d') ~= nil or
                char == "." then
                number = number .. char
            else -- scale and randomize
                number = number * scale_factor
                number = number * random_in_interval(lower_boundary, upper_boundary)
                processed_str = processed_str .. number .. char
                number = ""
                previous_was_number = false
            end
        else
            if string.match(char, '%d') ~= nil or
                char == "-" then

                number = number .. char
                previous_was_number = true
            else
                processed_str = processed_str .. char
                -- apply stuff
                previous_was_number = false
            end
        end
    end

    return processed_str
end