Pergunta

Eu tenho essa string em um script Lua:

one;two;;three;four;;five;;six;seven;

O primeiro char nunca será um ponto e vírgula. Os separadores do meio podem ser um semicolon único ou duplo, e o último char pode ser ou não um único semicolon.

Usando os padrões da Lua (e string.gsub()): Como posso combinar os semicolons duplos no meio para substituir aqueles por um único e excluir o último semicolon opcional?

A saída deve ser assim:

one;two;three;four;five;six;seven

Isso é possível usando um único padrão?

Foi útil?

Solução

Usando um padrão para substituir múltiplos ; para o único ;, e outro para remover o último ; é como isso

local str = "one;two;;three;four;;five;;six;seven;"
local result = str:gsub(';+', ';'):gsub(';*$', '')

Uma maneira possível de usar um único padrão é o seguinte:

local result = (str .. ";;;"):gsub(";+", function(s) 
                                             if s == ";" or s == ";;" then 
                                                 return ";" 
                                             else 
                                                 return "" 
                                             end 
                                         end)

O que estou tentando fazer é anexar três ; até o final da corda, então qualquer um ou dois ; deve ser substituído por um ;. E mais ;(Pode ser três ou quatro e deve estar no final) é substituído para a corda vazia.

Eu preferiria a solução com dois padrões, pois é mais claro.

Outras dicas

Que tal algo como isso:

function remove_extra_delim(s, delim)
    local t = {}
    for each in s:gmatch("[^"..delim.."]+") do
        table.insert(t, each)
    end
    return table.concat(t, delim)
end

teststr = "one;two;;three;four;;five;;six;seven;"
print(remove_extra_delim(teststr, ";"))

Saídas:

um dois três quatro cinco seis sete

Se a quantidade de semicolons for 1 ou 2, você pode simplesmente fazer

string:gsub(";;", ";")

Caso contrário, as outras respostas servirão.

É um pouco hacky, mas faz o truque:

x = test:gsub(";+(.?)",
  function(a)
    if a == "" then
      return ""
    else
      return ";" .. a
    end
  end)

(Nota: estou seguindo sua descrição exatamente, então eles corresponderão a um ou dois; mas não mais que dois, e zero final ou um; mas não mais que um)

-- Method one uses two patterns but it's simpler and my preferred one
s = 'one;two;;three;four;;five;;six;seven;'
s = s:gsub(';;',';'):gsub(';?$','')
print(s)

-- Method two uses one pattern (if you really MUST use only one pattern)
s = 'one;two;;three;four;;five;;six;seven;'
s = (s..';'):gsub(';;',';')
s = s:sub(1,#s-1)
print(s)
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top