Ruby 1.9이고 정규식에 명명 된 그룹을 사용하는 경우 모든 정규식을 하나의 속임수로 결합 할 수 있습니다. 무거운 짐을지는 클래스는 다음과 같습니다.
class BigPatternMatcher
def initialize(patterns_and_functions, no_match_function)
@regex = make_big_regex(patterns_and_functions)
@no_match_function = no_match_function
end
def match(s, context)
match = @regex.match(s)
context.send(function_name(match), match)
end
private
FUNC_GROUP_PREFIX = "func_"
FUNC_GROUP_REGEX = /^#{FUNC_GROUP_PREFIX}(.*)$/
def function_name(match)
if match
match.names.grep(FUNC_GROUP_REGEX).find do |name|
match[name]
end[FUNC_GROUP_REGEX, 1]
else
@no_match_function
end
end
def make_big_regex(patterns_and_functions)
patterns = patterns_and_functions.map do |pattern, function|
/(?<#{FUNC_GROUP_PREFIX}#{function}>#{pattern.source})/
end
Regexp.union(patterns)
end
end
어떻게 돌아가는지 돌아 보겠습니다. 이를 사용하려면 정규식 목록과 각 함수에 대해 호출해야하는 함수 이름이 필요합니다. 마지막으로, 여기가 사용되는 방법,
def foo(match)
p ["foo", match[:value]]
end
def bar(match)
p ["bar", match[:value]]
end
def default(match)
p ["default"]
end
을 그리고 : 일치가 없을 때 호출되는 것을 포함하여,
PATTERNS_AND_FUNCTIONS = [
[/ABC(?<value>\d+)/, :foo],
[/DEF(?<value>\d+)/, :bar],
]
그리고 기능을 : 단지라는 이름의 그룹을 사용해야합니다. BigPatternMatcher#match
일치하는 문자열을 사용하고 개체가되는 함수를 호출해야합니다
matcher = BigPatternMatcher.new(PATTERNS_AND_FUNCTIONS, :default)
matcher.match('blah ABC1 blah', self) # => ["foo", "1"
matcher.match('blah DEF2 blah', self) # => ["bar", "2"]
matcher.match('blah blah', self) # => ["default"]
가 작동하게하는 속임수의 배 아래를 참조하십시오.
BigPatternMatcher#make_big_regex
각 예컨대, 괄호 둘러싸여 |
로 구분 하나로 정규식을 모두 겸비한
/(ABC(?<value>\\d+))|(DEF(?<value>\\d+))/
하지만 충분하지 않습니다. 하위 표현식 중 하나가 일치 할 때 어떤 식으로 일치해야하는지, 따라서 호출 할 함수를 식별해야합니다. 지금
/(?<func_foo>ABC(?<value>\\d+))|(?<func_bar>DEF(?<value>\\d+))/
함수를 호출에의 우리가 경기에서 얼마나 보자 :이를 위해, 우리는 호출해야하는 기능에 따라 이름으로, 각각의 서브 표현 자체라는 이름의 그룹을 만들 수 있습니다 . 문자열을 감안할 때 :
"blah ABC1 blah"
다음 경기 그룹은 다음과 같습니다
#<MatchData "ABC1" func_foo:"ABC1" value:"1" func_bar:nil value:nil>
호출하는 기능을 알아낼하기 위해, 우리는 그냥 "func_"어느로 시작하는 이름을 가진 일치를 찾을 수있다 0이 아닌 값을가집니다. "func_"다음에 나오는 그룹 이름의 일부는 호출 할 함수의 이름을 지정합니다. 귀하의 질문에 간단한 기술에 대한이의 성능을 측정
는
독자들에게 운동이다.
어 ... 이제는 매끄러운 코덱입니다. 방금 그걸 생각해 냈어? – JnBrymn
@ 존, 감사합니다. 그렇습니다. 이전에 정규 표현식을 결합했지만 Ruby 1.8에서는 명명 된 그룹이 없으므로 매우 추했습니다. 그건 그렇고, 나는'BigPatternMatcher'를 편집하여 불일치 처리 버그를 수정하고 죽은 코드를 제거했습니다. 당신이 그것을 사용하기로 결정했다면, 당신은 그것을 다시 잡고 싶어 할 것입니다. –
제안 된 (사소한) 리펙토링 : 문자열을'|'와 결합하고'Regexp.new'로 전달하는 대신'Regexp.union'을 사용하십시오. 추가 제안 :이 코드에서 GitHub Gist를 만들면 앞으로 커뮤니티에서 사용할 수있게 될 것입니다. (사람들이 코드를 포크하고 수정 사항을 공유 할 수 있습니다 ...). –