2015-02-22 16 views
6

Così ho il seguente codice per dividere una stringa tra le spaziature:Lua: stringa divisa in parole meno citato

text = "I am 'the text'" 
for string in text:gmatch("%S+") do 
    print(string) 
end 

Il risultato:

I 
am 
'the 
text' 

ma ho bisogno di fare questo:

I 
am 
the text --[[yep, without the quotes]] 

Come posso fare questo?

Modifica: solo per completare la domanda, l'idea è di passare i parametri da un programma a un altro programma. Ecco la richiesta di pull che sto lavorando, attualmente in revisione: https://github.com/mpv-player/mpv/pull/1619

risposta

6

Ci possono essere modi per farlo con un'analisi intelligente, ma un modo alternativo potrebbe essere quello di tenere traccia di uno stato semplice e unire frammenti basati sul rilevamento di frammenti citati. Qualcosa di simile può funzionare:

local text = [[I "am" 'the text' and "some more text with '" and "escaped \" text"]] 
local spat, epat, buf, quoted = [=[^(['"])]=], [=[(['"])$]=] 
for str in text:gmatch("%S+") do 
    local squoted = str:match(spat) 
    local equoted = str:match(epat) 
    local escaped = str:match([=[(\*)['"]$]=]) 
    if squoted and not quoted and not equoted then 
    buf, quoted = str, squoted 
    elseif buf and equoted == quoted and #escaped % 2 == 0 then 
    str, buf, quoted = buf .. ' ' .. str, nil, nil 
    elseif buf then 
    buf = buf .. ' ' .. str 
    end 
    if not buf then print((str:gsub(spat,""):gsub(epat,""))) end 
end 
if buf then print("Missing matching quote for "..buf) end 

Questo stamperà:

I 
am 
the text 
and 
some more text with ' 
and 
escaped \" text 

aggiornato per gestire le citazioni miste ed è scappato. Aggiornato per rimuovere le virgolette. Aggiornato per gestire le parole citate.

+0

io preferirei qualcosa usando all'analisi delle stringhe. Ad ogni modo, mentre non ho detto nel post, ho bisogno di qualcosa su cui lavorare sia con virgolette singole che doppie, dato che l'idea di questo codice è di analizzare i parametri dalla shell. – m45t3r

+0

È facile aggiornare questa soluzione per farlo funzionare con virgolette singole e doppie; basta sostituire '"^'" 'con' [[^ ["']]]' e '"' $ "' con '[[''] $]]'. Potrebbe anche essere necessario verificare che la quotazione di apertura corrisponda a quella di chiusura. –

+0

È possibile eseguire con l'analisi delle stringhe, ma la soluzione è probabilmente più complessa (e non con una sola espressione poiché i modelli Lua non sono abbastanza potenti da esprimere ciò che serve). –

1

Prova questo:

text = [[I am 'the text' and '' here is "another text in quotes" and this is the end]] 

local e = 0 
while true do 
    local b = e+1 
    b = text:find("%S",b) 
    if b==nil then break end 
    if text:sub(b,b)=="'" then 
     e = text:find("'",b+1) 
     b = b+1 
    elseif text:sub(b,b)=='"' then 
     e = text:find('"',b+1) 
     b = b+1 
    else 
     e = text:find("%s",b+1) 
    end 
    if e==nil then e=#text+1 end 
    print("["..text:sub(b,e-1).."]") 
end 
+0

Risolto per gestire sia le virgolette singole che doppie e il testo tra virgolette vuoto. – lhf

1

Lua modelli non sono potente per gestire questo compito in modo corretto. Ecco una soluzione LPeg adattata dal Lua Lexer. Gestisce sia le virgolette singole che doppie.

local lpeg = require 'lpeg' 

local P, S, C, Cc, Ct = lpeg.P, lpeg.S, lpeg.C, lpeg.Cc, lpeg.Ct 

local function token(id, patt) return Ct(Cc(id) * C(patt)) end 

local singleq = P "'" * ((1 - S "'\r\n\f\\") + (P '\\' * 1))^0 * "'" 
local doubleq = P '"' * ((1 - S '"\r\n\f\\') + (P '\\' * 1))^0 * '"' 

local white = token('whitespace', S('\r\n\f\t ')^1) 
local word = token('word', (1 - S("' \r\n\f\t\""))^1) 

local string = token('string', singleq + doubleq) 

local tokens = Ct((string + white + word)^0) 


input = [["This is a string" 'another string' these are words]] 
for _, tok in ipairs(lpeg.match(tokens, input)) do 
    if tok[1] ~= "whitespace" then 
    if tok[1] == "string" then 
     print(tok[2]:sub(2,-2)) -- cut off quotes 
    else 
     print(tok[2]) 
    end 
    end 
end 

uscita:

This is a string 
another string 
these 
are 
words