Ruby

2011-06-23 25 views
9

içinde joker karakter dizisi eşleşmesi Dizelere basit joker/glob eşleştirmesi sağlayan bir yardımcı işlev/modül yazmak istiyorum. Normal ifadeler kullanmama sebebim, kullanıcının bir çeşit yapılandırma dosyası kullanarak eşleşecek kalıpları sağlamasıyla sonuçlanan kişi olacaktır. Ben kararlı bir joker bulamadım - joker denedim ama ayar sorunları vardı.Ruby

Aradığım işlevsellik basit. Ben mümkün olduğunca verimli olmak için bu istiyorum

pattern | test-string   | match 
========|=====================|==================== 
*hn  | john, johnny, hanna | true , false, false  # wildcard , similar to /hn$/i 
*hn* | john, johnny, hanna | true , true , false  # like /hn/i 
hn  | john, johnny, hanna | false, false, false  # /^hn$/i 
*h*n* | john, johnny, hanna | true , true , true 
etc... 

: Örneğin, aşağıdaki desenler verilen Burada maçları. Desen dizelerinden düzenli ifadeler oluşturmayı düşündüm, ancak bu çalışma zamanında yapmak için oldukça verimsiz görünüyordu. Bu uygulama ile ilgili herhangi bir öneriniz var mı? Teşekkürler.

DÜZENLEME: Bu test edilmemiştir:: D

cevap

13

görmüyorum ben bu methoid

PS regexp'in dönmelidir yakut 1.8.7

+0

Ben john awesome'' olan ' '* örneğin hn'', o' gerekiyor' durumunda düşünüyorum true olarak geri dönmek ve '/.* hn $ /' ile eşleşmeyecek –

+0

Bilgisayarımda globların çalıştığı yol görünmüyor (Mac OSX Leopard) https://gist.github.com/1041942 –

+0

I joker karakterimin amacım için globden daha doğru olduğunu varsayalım - '' hn '' durumunda e desenden önce ve sonra her şey eşleşecek, ve sonra hiçbir şey; '' john '' için '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' '' ''. teşekkürler – sa125

1
def create_regex(pattern) 
if pattern[0,1] != '*' 
    pattern = '[^\w\^]' + pattern 
end 
if pattern[-1,1] != '*' 
    pattern = pattern + '[^\w$]' 
end 
return Regexp.new(pattern.gsub(/\*/, '.*?')) 
end 

kullanıyorum neden verimsiz olacağını düşünüyorsun. Bu tür şeylerle ilgili tahminler çok nadiren güvenilmezdir, daha hızlı bir yol bulmak için geriye doğru eğilmeden önce çok yavaş olduğuna karar vermelisiniz. Ve sonra bu sorun burada yatıyor olduğundan emin olmak için profil gerektiğini

Neyse, bunu yapmak gibi bir şey oldukça kolay olmalıdır (btw 1,9 geçişin getirdiği 3-4x hız artışı ortalama vardır) :

class Globber 
    def self.parse_to_regex(str) 
    escaped = Regexp.escape(str).gsub('\*','.*?') 
    Regexp.new "^#{escaped}$", Regexp::IGNORECASE 
    end 

    def initialize(str) 
    @regex = self.class.parse_to_regex str 
    end 

    def =~(str) 
    !!(str =~ @regex) 
    end 
end 


glob_strs = { 
    '*hn' => [['john', true, ], ['johnny', false,], ['hanna', false]], 
    '*hn*' => [['john', true, ], ['johnny', true, ], ['hanna', false]], 
    'hn'  => [['john', false,], ['johnny', false,], ['hanna', false]], 
    '*h*n*' => [['john', true, ], ['johnny', true, ], ['hanna', true ]], 
} 

puts glob_strs.all? { |to_glob, examples| 
    examples.all? do |to_match, expectation| 
    result = Globber.new(to_glob) =~ to_match 
    result == expectation 
    end 
} 
# >> true 
+2

bazı düzenleme yapılması - teşekkürler sözdizimi hatalarını işaret için - çok fazla perl/php: D –