2012-07-09 35 views
8

Tôi đang viết một tiện ích grep ở Lua cho thiết bị di động chạy Windows CE 6/7, nhưng tôi đã gặp phải một số vấn đề khi triển khai mẫu so khớp phân biệt chữ hoa chữ thường. Các giải pháp rõ ràng của việc chuyển đổi mọi thứ thành chữ hoa (hoặc thấp hơn) không hoạt động nên chỉ đơn giản là do các lớp ký tự.Kết hợp mẫu Lua phân biệt chữ hoa chữ thường

Điều duy nhất tôi có thể nghĩ là chuyển đổi các chữ trong mẫu thành chữ hoa.

Dưới đây là những gì tôi có cho đến nay:

function toUpperPattern(instr) 
    -- Check first character 
    if string.find(instr, "^%l") then 
     instr = string.upper(string.sub(instr, 1, 1)) .. string.sub(instr, 2) 
    end 
    -- Check the rest of the pattern 
    while 1 do 
     local a, b, str = string.find(instr, "[^%%](%l+)") 
     if not a then break end 
     if str then 
      instr = string.sub(instr, 1, a) .. string.upper(string.sub(instr, a+1, b)) .. string.sub(instr, b + 1) 
     end 
    end 
    return instr 
end 

Tôi ghét phải thừa nhận mất bao lâu để có được thậm chí là xa, và tôi vẫn có thể thấy ngay lập tức có được sẽ trở thành vấn đề với những thứ như trăm thoát dấu hiệu '%%'

Tôi nhận ra đây phải là một vấn đề khá phổ biến, nhưng dường như tôi không thể tìm thấy nhiều về chủ đề này. Có cách nào dễ dàng hơn (hoặc ít nhất là hoàn thành) để thực hiện việc này không? Tôi bắt đầu phát điên lên đây ... Hy vọng bạn có rất nhiều người có thể khai sáng cho tôi!

Trả lời

9

Hãy thử một cái gì đó như thế này:

function case_insensitive_pattern(pattern) 

    -- find an optional '%' (group 1) followed by any character (group 2) 
    local p = pattern:gsub("(%%?)(.)", function(percent, letter) 

    if percent ~= "" or not letter:match("%a") then 
     -- if the '%' matched, or `letter` is not a letter, return "as is" 
     return percent .. letter 
    else 
     -- else, return a case-insensitive character class of the matched letter 
     return string.format("[%s%s]", letter:lower(), letter:upper()) 
    end 

    end) 

    return p 
end 

print(case_insensitive_pattern("xyz = %d+ or %% end")) 

mà in:

[xX][yY][zZ] = %d+ [oO][rR] %% [eE][nN][dD]
+1

Tuyệt vời. Tôi đang vẽ một khoảng trống. BTW: bạn có thể nói 'pattern: gsub' giống như bạn đã nói' letter: lower'. Bạn thậm chí có thể nói '('[% s% s]'): định dạng' nhưng đó là một chút weirder. – Mud

+0

Vâng, 'string.format (...)' trông quen thuộc hơn '('[% s% s]'): định dạng (...)', nhưng tôi thích 'mẫu: gsub (...) 'tốt hơn! Cảm ơn. –

+0

Không thể tin được. Nhưng một câu hỏi ... Làm thế nào mà không chuyển đổi một cái gì đó như '%% test' thành' %% [tT] est'? Trận đấu đó có bị bỏ qua vì lần lặp trước đó có khớp với cả '%%' không? Có lẽ bộ não của tôi chỉ là một chút chiên hôm nay:/ – Nubbychadnezzar

0

Lua 5.1, LPeg v0.12

do 
    local p = re.compile([[ 
     pattern <- ({b}/{escaped}/brackets/other)+ 
     b  <- "%b" . . 
     escaped <- "%" . 
     brackets <- { "[" ([^]%]+/escaped)* "]" } 
     other <- [^[%]+ -> cases 
    ]], { 
     cases = function(str) return (str:gsub('%a',function(a) return '['..a:lower()..a:upper()..']' end)) end 
    }) 
    local pb = re.compile([[ 
     pattern <- ({b}/{escaped}/brackets/other)+ 
     b  <- "%b" . . 
     escaped <- "%" . 
     brackets <- {: {"["} ({escaped}/bcases)* {"]"} :} 
     bcases <- [^]%]+ -> bcases 
     other <- [^[%]+ -> cases 
    ]], { 
     cases = function(str) return (str:gsub('%a',function(a) return '['..a:lower()..a:upper()..']' end)) end 
     , bcases = function(str) return (str:gsub('%a',function(a) return a:lower()..a:upper() end)) end 
    }) 
    function iPattern(pattern,brackets) 
     ('sanity check'):find(pattern) 
     return table.concat({re.match(pattern, brackets and pb or p)}) 
    end 
end 

local test     = '[ab%c%]d%%]+ o%%r %bnm' 
print(iPattern(test))  -- [ab%c%]d%%]+ [oO]%%[rR] %bnm 
print(iPattern(test,true)) -- [aAbB%c%]dD%%]+ [oO]%%[rR] %bnm 
print(('qwe [%D]% O%r n---m asd'):match(iPattern(test, true))) -- %D]% O%r n---m 

tinh khiết phiên bản Lua:

012.

Cần phân tích tất cả các ký tự trong chuỗi để chuyển đổi thành một mẫu đúng vì các mẫu Lua không có các thay đổi như trong regexps (abc | something).

function iPattern(pattern, brackets) 
    ('sanity check'):find(pattern) 
    local tmp = {} 
    local i=1 
    while i <= #pattern do    -- 'for' don't let change counter 
     local char = pattern:sub(i,i) -- current char 
     if char == '%' then 
      tmp[#tmp+1] = char   -- add to tmp table 
      i=i+1      -- next char position 
      char = pattern:sub(i,i) 
      tmp[#tmp+1] = char 
      if char == 'b' then   -- '%bxy' - add next 2 chars 
       tmp[#tmp+1] = pattern:sub(i+1,i+2) 
       i=i+2 
      end 
     elseif char=='[' then   -- brackets 
      tmp[#tmp+1] = char 
      i = i+1 
      while i <= #pattern do 
       char = pattern:sub(i,i) 
       if char == '%' then  -- no '%bxy' inside brackets 
        tmp[#tmp+1] = char 
        tmp[#tmp+1] = pattern:sub(i+1,i+1) 
        i = i+1 
       elseif char:match("%a") then -- letter 
        tmp[#tmp+1] = not brackets and char or char:lower()..char:upper() 
       else       -- something else 
        tmp[#tmp+1] = char 
       end 
       if char==']' then break end -- close bracket 
       i = i+1 
      end 
     elseif char:match("%a") then -- letter 
      tmp[#tmp+1] = '['..char:lower()..char:upper()..']' 
     else 
      tmp[#tmp+1] = char   -- something else 
     end 
     i=i+1 
    end 
    return table.concat(tmp) 
end 

local test     = '[ab%c%]d%%]+ o%%r %bnm' 
print(iPattern(test))  -- [ab%c%]d%%]+ [oO]%%[rR] %bnm 
print(iPattern(test,true)) -- [aAbB%c%]dD%%]+ [oO]%%[rR] %bnm 
print(('qwe [%D]% O%r n---m asd'):match(iPattern(test, true))) -- %D]% O%r n---m 
+0

Chào mừng bạn đến với stackoverflow. Câu trả lời hay nhất thường không chỉ là mã. Họ giải thích mã, hoặc nơi OP đã đi sai trong nỗ lực của họ. –

Các vấn đề liên quan