Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/ruby/25.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby中的通配符字符串匹配_Ruby_Pattern Matching_Glob_String Matching - Fatal编程技术网

Ruby中的通配符字符串匹配

Ruby中的通配符字符串匹配,ruby,pattern-matching,glob,string-matching,Ruby,Pattern Matching,Glob,String Matching,我想编写一个实用函数/模块,它将提供与字符串的简单通配符/全局匹配。我不使用正则表达式的原因是,最终用户将使用某种配置文件提供匹配的模式。我找不到任何这样的宝石是稳定的-尝试过的小丑,但它有问题设置 我想要的功能很简单。例如,给定以下模式,以下是匹配项: pattern | test-string | match ========|=====================|==================== *hn | john, johnny, hanna |

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

我想要的功能很简单。例如,给定以下模式,以下是匹配项:

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

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
此MethodId应返回您的regexp


附言:它没有经过测试:我不明白你为什么认为它效率低下。关于这类事情的预测是出了名的不可靠,你应该决定它太慢了,然后再回头去寻找更快的方法。然后你应该分析它,以确保这是问题所在(顺便说一句,从切换到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

我认为以
'*hn'
为例,他需要
'john's awesome'
也返回true,而
/.*hn$/
将不会匹配globs在我的计算机上的工作方式(Mac OSX Leopard)我认为通配符比glob更准确——对于
'*hn'
上的情况,我希望模式之前和之后的所有内容都要匹配,后面什么都不匹配;所以
true
对于
'john'
false
对于
'john is..
。感谢与此解决方案一致的内容。完成了一些编辑-感谢指出语法错误-perl/php:D太多了