2012-07-09 2 views
8

Windows CE 6/7을 실행하는 모바일 장치 용 Lua의 grep 유틸리티를 작성하고 있지만 대/소문자를 구분하지 않는 일치 패턴 구현과 관련된 몇 가지 문제가 있습니다. 모든 것을 대문자 (또는 더 낮은)로 변환하는 분명한 해결책은 문자 클래스로 인해 그렇게 간단하게 작동하지 않습니다.대소 문자 구별 없음 Lua 패턴 일치

내가 생각할 수있는 유일한 다른 점은 패턴 자체의 리터럴을 대문자로 변환하는 것입니다. 여기

는 지금까지이 작업은 다음과 같습니다

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 

나는 심지어 멀리 얻을하는 데 걸린 시간을 인정하기 싫어, 난 여전히 탈출 %로 같은 것들에 문제가있을거야 바로 볼 수 있습니다 signs '%%'

나는 이것이 매우 일반적인 문제라고 생각했지만, 주제에 대해 많은 것을 찾지 못했습니다. 더 쉬운 방법 (또는 적어도 완전한 방법)이 있습니까? 나는 여기에 미쳐 가기 시작하고있다. ... 루아 루스가 나에게 가르쳐 줄 것을 기대하고있다! 이 같은

답변

9

시도 뭔가 :

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")) 

인쇄 :

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

굉장합니다. 나는 공백을 그리고 있었다. BTW :'letter : lower'라고 말한 것처럼'pattern : gsub'라고 말할 수 있습니다. '('[% s % s]') : format'이라고 말할 수도 있습니다.하지만 좀 이상합니다. – Mud

+0

예 :'string.format (...)'은'('[% s % s]') : format (...)'보다 친숙 해 보이지만'pattern : gsub (...) '더 나아! 감사. –

+0

인크 레 더블. 하지만 한 가지 질문은 ... 어떻게'%% test'를'%% [tT] est'로 변환하지 않습니까? 이전 반복이 '%%'와 (과) 일치하기 때문에 일치가 건너 뛰었습니까? 어쩌면 내 두뇌는 오늘 조금 튀긴 것 같습니다 :/ – Nubbychadnezzar

0

루아 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 

순수 루아 버전 :

루아 패턴에 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

에 오신 것을 환영합니다. 가장 좋은 답변은 일반적으로 코드가 아닙니다. 그들은 코드를 설명하거나, OP가 자신의 시도에서 잘못되었을 때를 설명합니다. –