如何在 Lua 中撤销 string.gmatch 对字符串特定部分的操作

所以我正在使用 Lua 并通过空格分割字符串来编写某种子语言。我正在尝试使其不分割括号内的任何内容,我已经到达了可以检测是否存在括号的阶段。但我希望反转括号内字符串的 gmatching,因为我希望保留其中的字符串。

local function split(strng)
    local __s={}
    local all_included={}
    local flag_table={}
    local uncompiled={}
    local flagged=false
    local flagnum=0

    local c=0
    for i in string.gmatch(strng,'%S+') do
        c=c+1
        table.insert(all_included,i)
        if(flagged==false)then
            if(string.find(i,'%('or'%['or'%{'))then
                flagged=true
                flag_table[tostring(c)]=1
                table.insert(uncompiled,i)
                print'flagged'
            else
                table.insert(__s,i)
            end
        elseif(flagged==true)then
            table.insert(uncompiled,i)
            if(string.find(i,'%)' or '%]' or '%}'))then
                flagged=false
                local __=''
                for i=1,#uncompiled do
                    __=__ .. uncompiled[i]
                end
                table.insert(__s,__)
                print'unflagged'
            end
        end
    end

    return __s;
end

这是我的分割代码

点赞
用户436275
用户436275

我根本就不会使用 gmatch

local input = "这是一个字符串(包含一些(好吧,很多)讨厌的)括号,并应该被拆分。该字符串包含双空格。应该做什么?以及尾随空格呢?"

local pos = 1
local words = {}
local last_start = pos
while pos <= #input do
    local char = string.byte(input, pos)

    if char == string.byte(" ") then
        table.insert(words, string.sub(input, last_start, pos - 1))
        last_start = pos + 1
    elseif char == string.byte("(") then
        local depth = 1
        while depth ~= 0 and pos + 1 < #input do
            local char = string.byte(input, pos + 1)
            if char == string.byte(")") then
                depth = depth - 1
            elseif char == string.byte("(") then
                depth = depth + 1
            end
            pos = pos + 1
        end
    end
    pos = pos + 1
end
table.insert(words, string.sub(input, last_start))

for k, v in pairs(words) do
    print(k, "'" .. v .. "'")
end

输出:

1   ''
2   '这'
3   '是'
4   '一个'
5   '字符串'
6   '(包含一些(好吧,很多)讨厌的)'
7   '括号'
8   '并'
9   '应该'
10  '被'
11  '拆分。'
12  '该'
13  '字符串包含双空格。应该做什么?以及尾随空格呢?'

关于尾随空格和其他类似问题的思考留给读者作为练习。我试图展示一些可能存在的问题。此外,我仅考虑了一种括号,因为我不想思考 this (string} should be ]parsed

哦,如果嵌套括号不是一个问题:上面的大部分代码都可以替换为一个调用 string.find(input, ")", pos, true) 来查找闭合括号。

请注意,您不能像在您的代码中尝试的那样使用或或并模式。

"%(" or "%[" 等于 "%("

Lua 将按从左到右的顺序解释该表达式。"%(" 是一个真值,Lua 将该表达式简化为 "%(",逻辑上与完整表达式相同。

因此,string.find(i,'%('or'%['or'%{') 只能在 i 中找到 (

2019-03-19 07:37:29
用户7552
用户7552

作为对 Uli 答案的一种类似但略有不同的方法,我会首先按括号进行拆分。 然后可以将奇数字段按空格拆分:

split = require("split") -- https://luarocks.org/modules/telemachus/split

split__by_parentheses = function(input)
    local fields = {}
    local level = 0
    local field = ""

    for i = 1, #input do
        local char = input:sub(i, i)

        if char == "(" then
            if level == 0 then
                -- add non-parenthesized field to list
                fields[#fields+1] = field
                field = ""
            end
            level = level + 1
        end

        field = field .. char

        if char == ")" then
            level = level - 1
            assert(level >= 0, 'Mismatched parentheses')
            if level == 0 then
                -- add parenthesized field to list
                fields[#fields+1] = field
                field = ""
            end
        end
    end

    assert(level == 0, 'Mismatched parentheses')
    fields[#fields+1] = field
    return fields
end

input = " this is a string (containg some (well, many) annoying) parentheses and should be split. The string contains  double   spaces. What should be done? And what about trailing spaces? "

fields = split__by_parentheses(input)

for i, field in ipairs(fields) do
    print(("%d\t'%s'"):format(i, field))
    if i % 2 == 1 then
        for j, word in ipairs(split.split(field)) do
            print(("\t%d\t%s"):format(j, word))
        end
    end
end

输出结果:

1       ' this is a string '
        1
        2       this
        3       is
        4       a
        5       string
        6
2       '(containg some (well, many) annoying)'
3       ' parentheses and should be split. The string contains  double   spaces. What should be done? And what about trailing spaces? '
        1
        2       parentheses
        3       and
        4       should
        5       be
        6       split.
        7       The
        8       string
        9       contains
        10      double
        11      spaces.
        12      What
        13      should
        14      be
        15      done?
        16      And
        17      what
        18      about
        19      trailing
        20      spaces?
        21
2019-03-19 15:14:43