2011-06-23 68 views
9

我想編寫一個實用程序函數/模塊,它將爲字符串提供簡單的通配符/ glob匹配。我不使用正則表達式的原因是,用戶將是最終提供模式以使用某種配置文件進行匹配的人。我找不到任何這種穩定的寶石 - 嘗試了小丑,但它有問題設置。Ruby中的通配符字符串匹配

我正在尋找的功能很簡單。例如,給定以下模式,這裏是匹配:

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... 

我希望這樣做盡可能高效。我想從模式字符串中創建正則表達式,但在運行時看起來效率相當低。有關此實施的任何建議?謝謝。

編輯:我使用Ruby 1.8.7

回答

13

我沒有看到爲什麼你認爲這將是低效的。對這些事情的預測是非常不可靠的,你應該認定它太慢了,然後再向後彎來尋找更快的方法。然後,你應該配置它,以確保這是問題所在(順便說一下,平均從切換到1.9的3-4倍速度提升)

無論如何,這應該是很容易做到這一點, :

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 
+0

我想在'「* hn''例如,他需要'」的情況下,約翰是awesome''以'/.* hn $ /'不匹配 –

+0

似乎並不是我的電腦上運行的方式(Mac OSX Leopard)https://gist.github.com/1041942 –

+0

I假設通配符比glob更準確,我的目的 - 對於'* hn''我喜歡e事前和事後的一切 - 匹配的模式,以及之後的事情;所以'john''是'true',''john是''false'是''。謝謝 – 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 

這methoid應該回到你的正則表達式

PS:這是沒有經過測試:d

+2

做一些編輯 - 感謝您指出語法錯誤 - 太多的Perl/PHP:d –