2012-07-09 23 views
8

Windows CE 6/7 çalıştıran mobil aygıtlarımız için Lua'da bir grep yardımcı programı yazıyorum, ancak büyük/küçük harf duyarlı olmayan eşleşme desenlerini uygulayan bazı sorunlarda çalışıyorum. Her şeyi büyük harfe dönüştüren açık çözüm (ya da daha düşük), karakter sınıflarından dolayı bu kadar kolay çalışmaz.Büyük/küçük harf duyarlı Lua desen eşlemesi

Düşünebildiğim tek diğer şey, modeldeki değişmezleri büyük harfe dönüştürmektir. İşte

Ben bugüne kadar ne var:

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 

ben bile o kadar olsun ne kadar sürdüğünü kabul etmekten nefret ediyorum ve hala kaçan yüzde gibi şeyler ile ilgili sorunlar olacaksa olan hemen görebilirsiniz '%%' belirtileri '

Bunun oldukça yaygın bir sorun olması gerektiğini düşündüm, ancak konuyla ilgili fazla bir şey göremiyorum. Bunu yapmak için daha kolay (veya en azından tamamlanmış) yollar var mı? Burada çıldırmaya başlıyorum ... Seni umut ediyorum Lua Gurus dışarıda beni aydınlatabilir! Böyle

cevap

9

deneyin şey:

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

yazdırır:

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

Awesome. Boş çiziyordum. Btw: diyelim ki 'desen: gsub' diyebilirsiniz: Hatta ('[% s% s]'): format' diyebilirsiniz, ancak bu biraz tuhaftır. – Mud

+0

Evet, 'string.format (...)' '('[% s% s]'): format (...)' dan daha tanıdık görünüyor, ancak ben 'pattern: gsub (...) 'daha iyi! Teşekkürler. –

+0

İnanılmaz. Ama bir soru ... Bu, %% test gibi bir şeyi "%% [tT] est" olarak nasıl dönüştürmez? Bu eşleme atlandı mı, önceki yineleme hem '%%' ile eşleşecek miydi? Belki beynim bugün biraz kızardı:/ – 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 

Saf Lua sürümü:

Dizedeki tüm karakterleri doğru bir forma dönüştürmek için analiz etmek gerekir, çünkü Lua desenleri normal ifadelerde (abc | bir şey gibi) bulunmaz.

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

Yığın akışına hoş geldiniz. En iyi cevaplar genellikle sadece kod değildir. Kodu açıklar ya da OP'nin girişimlerde yanlış gittiği yerlerdir. –

İlgili konular