2015-02-22 10 views
6

Vì vậy, tôi đã đoạn mã sau để tách một chuỗi giữa khoảng trắng:Lua: chia chuỗi thành lời trừ khi trích dẫn

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

Kết quả:

I 
am 
'the 
text' 

Nhưng tôi cần phải làm điều này:

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

Tôi làm cách nào để thực hiện việc này?

Chỉnh sửa: chỉ để bổ sung cho câu hỏi, ý tưởng là chuyển các tham số từ chương trình sang chương trình khác. Đây là yêu cầu kéo mà tôi đang làm việc, hiện đang được xem xét: https://github.com/mpv-player/mpv/pull/1619

Trả lời

6

Có thể có cách để làm điều này với phân tích cú pháp thông minh, nhưng một cách khác có thể là theo dõi trạng thái đơn giản và hợp nhất các mảnh dựa trên phát hiện trích đoạn. Một cái gì đó như thế này có thể làm việc:

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 

này sẽ in:

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

cập nhật để xử lý dấu ngoặc kép hỗn hợp và trốn thoát. Đã cập nhật để xóa dấu ngoặc kép. Đã cập nhật để xử lý các từ được trích dẫn.

+0

Tôi muốn một cái gì đó bằng chuỗi phân tích cú pháp. Dù sao, trong khi tôi đã không nói trong bài viết tôi cần một cái gì đó để làm việc cả hai với dấu nháy đơn và đôi, vì ý tưởng của mã này là để phân tích các thông số từ trình bao. – m45t3r

+0

Thật dễ dàng để cập nhật giải pháp này để làm cho nó hoạt động với các dấu nháy đơn và kép; chỉ cần thay thế '"^'" 'bằng' [[^ ["']]]' và '"' $ "' bằng '[[[']]]. Bạn cũng có thể cần phải kiểm tra xem báo giá mở có khớp với giá đóng không. –

+0

Có thể thực hiện với phân tích cú pháp chuỗi, nhưng giải pháp có thể phức tạp hơn (và không phải với một biểu thức như các mẫu Lua không đủ mạnh để thể hiện những gì bạn cần). –

1

Hãy thử điều này:

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

Cố định để xử lý cả dấu ngoặc đơn và dấu ngoặc kép và văn bản được trích dẫn trống. – lhf

1

Lua Patterns không mạnh mẽ để xử lý công việc này đúng cách. Đây là giải pháp LPeg được điều chỉnh từ Lua Lexer. Nó xử lý cả dấu nháy kép và đơn.

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 
Các vấn đề liên quan