2015-02-22 13 views
6
zitierte

So habe ich den folgenden Code eine Zeichenfolge zwischen Leerzeichen aufzuteilen:Lua: split-String in Worte, es sei denn

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

Das Ergebnis:

I 
am 
'the 
text' 

aber ich brauche, dies zu tun:

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

Wie kann ich das tun?

Bearbeiten: nur um die Frage zu ergänzen, besteht die Idee darin, Parameter von einem Programm zu einem anderen Programm zu übergeben. Hier ist die Pull-Anfrage, die ich arbeite, derzeit im Rückblick: https://github.com/mpv-player/mpv/pull/1619

Antwort

6

Es kann Wege geben, dies mit cleveren Parsing zu tun, aber eine alternative Möglichkeit könnte sein, einen einfachen Zustand zu verfolgen und Fragmente basierend auf Erkennung von zusammenführen zitierte Fragmente. So etwas wie dies funktionieren kann:

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 

Dieser Druck wird:

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

Aktualisiert gemischt und entkam Anführungszeichen zu behandeln. Aktualisiert, um Zitate zu entfernen. Aktualisiert, um mit zitierten Wörtern umzugehen.

+0

Ich würde etwas mit String-Parsing bevorzugen. Wie auch immer, während ich in der Post nicht gesagt habe, brauche ich etwas mit einfachen und doppelten Anführungszeichen zu arbeiten, da die Idee dieses Codes ist, Parameter aus der Shell zu analysieren. – m45t3r

+0

Es ist einfach, diese Lösung zu aktualisieren, damit sie mit einfachen und doppelten Anführungszeichen funktioniert. Ersetzen Sie einfach ''^'" 'durch' [[^ ['']]] 'und' "'$" 'durch' [[[' "] $]]'. Möglicherweise müssen Sie auch überprüfen, ob das Eröffnungsangebot mit dem Schlussangebot übereinstimmt. –

+0

Es ist möglich, mit String-Parsing zu tun, aber die Lösung ist wahrscheinlich komplexer (und nicht mit einem Ausdruck, da Lua-Muster nicht stark genug sind, um das auszudrücken, was Sie brauchen). –

1

Versuchen Sie folgendes:

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

Korrektur für einfache und doppelte Anführungszeichen und leeren zitierten Text. – lhf

1

Lua Patterns sind nicht leistungsfähig diese Aufgabe richtig zu handhaben. Hier ist eine LPeg Lösung aus der Lua Lexer. Es behandelt sowohl einfache als auch doppelte Anführungszeichen.

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 

Ausgang:

This is a string 
another string 
these 
are 
words 
Verwandte Themen