2012-07-09 5 views
8

Sto scrivendo un'utilità grep in Lua per i nostri dispositivi mobili che eseguono Windows CE 6/7, ma ho riscontrato alcuni problemi nell'implementazione di modelli di corrispondenza senza distinzione tra maiuscole e minuscole. L'ovvia soluzione di convertire tutto in maiuscolo (o in basso) non funziona così semplicemente a causa delle classi di caratteri.Corrispondenza delle maiuscole senza distinzione tra maiuscole e minuscole

L'unica altra cosa che posso pensare è convertire i letterali nel modello stesso in maiuscolo.

Ecco quello che ho finora:

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 

Odio ammetterlo quanto tempo ha preso per ottenere anche così lontano, e posso ancora vedere subito ci stanno per essere problemi con le cose come cento sfuggito segni '%%'

Ho pensato che questo fosse un problema abbastanza comune, ma non riesco a trovare molto sull'argomento. Esistono modi più semplici (o almeno completi) per farlo? Sto iniziando a impazzire qui ... Sperando che i guru della Lua là fuori possano illuminarmi!

risposta

9

provare qualcosa di simile:

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

che stampa:

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

Impressionante. Stavo disegnando uno spazio vuoto. A proposito: puoi dire 'modello: gsub' proprio come hai detto' lettera: inferiore'. Potresti anche dire '('[% s% s]'): format' ma è un po 'strano. – Mud

+0

Sì, 'string.format (...)' sembra più familiare di '('[% s% s]'): format (...)', ma mi piace 'pattern: gsub (...) 'meglio! Grazie. –

+0

Incredibile. Ma una domanda ... Come si fa a non convertire qualcosa come '%% test' a' %% [tT] est'? Questa corrispondenza è stata saltata perché la precedente iterazione avrebbe coinciso con entrambi "%%"? Forse il mio cervello è solo un po 'fritto oggi:/ – 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 

versione Pure Lua:

012.

È necessario analizzare tutti i caratteri nella stringa per convertirli in un modello corretto perché i modelli Lua non hanno alternanze come in espressioni regolari (abc | qualcosa).

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

Benvenuti in StackOverflow. Le migliori risposte di solito non sono solo codice. Spiegano il codice, o dove l'OP è andato storto nei loro tentativi. –