Ruby中的通配符字符串匹配

sa1*_*125 10 ruby glob pattern-matching string-matching

我想编写一个实用程序函数/模块,它将为字符串提供简单的通配符/ glob匹配.我没有使用正则表达式的原因是用户将最终使用某种配置文件提供匹配的模式.我找不到任何这样稳定的宝石 - 试过小丑,但是设置有问题.

我正在寻找的功能很简单.例如,给定以下模式,以下是匹配:

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...
Run Code Online (Sandbox Code Playgroud)

我希望这样做尽可能高效.我考虑过从模式字符串创建正则表达式,但这在运行时似乎效率很低.有关此实施的任何建议吗?谢谢.

编辑:我正在使用ruby 1.8.7

Jos*_*eek 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
Run Code Online (Sandbox Code Playgroud)