Lua: split the string into words if not specified

So, I have the following code for splitting a string between spaces:

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

Result:

 I am 'the text' 

But I need to do this:

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

How can i do this?

Edit: just to complement the question, the idea is to pass parameters from the program to another program. Here is the transfer request that I am currently working on, currently in a review: https://github.com/mpv-player/mpv/pull/1619

+6
source share
3 answers

There may be ways to do this with smart parsing, but an alternative way would be to track a simple state and merge fragments based on the detection of quoted fragments. Something like this might work:

 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 

This will print:

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

Updated to handle mixed and shielded quotes. Updated to remove quotes. Updated to handle quoted words.

+6
source

Try the following:

 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 
+1
source

Lua templates are inefficient for handling this task properly. The following is an LPeg solution adapted from Lua Lexer . It processes both single and double quotes.

 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 

Output:

 This is a string another string these are words 
+1
source

Source: https://habr.com/ru/post/982863/