# Matches a regular expression against a string and returns an array containing the match
# and any matched capturing groups.
#
# The first argument is a string or array of strings. The second argument is either a
# regular expression, regular expression represented as a string, or Regex or Pattern
# data type that the function matches against the first argument.
#
# The returned array contains the entire match at index 0, and each captured group at
# subsequent index values. If the value or expression being matched is an array, the
# function returns an array with mapped match results.
#
# If the function doesn't find a match, it returns 'undef'.
#
# @example Matching a regular expression in a string
#
# ```puppet
# $matches = "abc123".match(/[a-z]+[1-9]+/)
# # $matches contains [abc123]
# ```
#
# @example Matching a regular expressions with grouping captures in a string
#
# ```puppet
# $matches = "abc123".match(/([a-z]+)([1-9]+)/)
# # $matches contains [abc123, abc, 123]
# ```
#
# @example Matching a regular expression with grouping captures in an array of strings
#
# ```puppet
# $matches = ["abc123","def456"].match(/([a-z]+)([1-9]+)/)
# # $matches contains [[abc123, abc, 123], [def456, def, 456]]
# ```
#
# @since 4.0.0
#
Puppet::Functions.create_function(:match) do
dispatch :match do
param 'String', :string
param 'Variant[Any, Type]', :pattern
end
dispatch :enumerable_match do
param 'Array[String]', :string
param 'Variant[Any, Type]', :pattern
end
def initialize(closure_scope, loader)
super
# Make this visitor shared among all instantiations of this function since it is faster.
# This can be used because it is not possible to replace
# a puppet runtime (where this function is) without a reboot. If you model a function in a module after
# this class, use a regular instance variable instead to enable reloading of the module without reboot
#
@@match_visitor ||= Puppet::Pops::Visitor.new(self, "match", 1, 1)
end
# Matches given string against given pattern and returns an Array with matches.
# @param string [String] the string to match
# @param pattern [String, Regexp, Puppet::Pops::Types::PPatternType, Puppet::Pops::PRegexpType, Array] the pattern
# @return [Array<String>] matches where first match is the entire match, and index 1-n are captures from left to right
#
def match(string, pattern)
@@match_visitor.visit_this_1(self, pattern, string)
end
# Matches given Array[String] against given pattern and returns an Array with mapped match results.
#
# @param array [Array<String>] the array of strings to match
# @param pattern [String, Regexp, Puppet::Pops::Types::PPatternType, Puppet::Pops::PRegexpType, Array] the pattern
# @return [Array<Array<String, nil>>] Array with matches (see {#match}), non matching entries produce a nil entry
#
def enumerable_match(array, pattern)
array.map {|s| match(s, pattern) }
end
protected
def match_Object(obj, s)
msg = _("match() expects pattern of T, where T is String, Regexp, Regexp[r], Pattern[p], or Array[T]. Got %{klass}") % { klass: obj.class }
raise ArgumentError, msg
end
def match_String(pattern_string, s)
do_match(s, Regexp.new(pattern_string))
end
def match_Regexp(regexp, s)
do_match(s, regexp)
end
def match_PTypeAliasType(alias_t, s)
match(s, alias_t.resolved_type)
end
def match_PVariantType(var_t, s)
# Find first matching type (or error out if one of the variants is not acceptable)
result = nil
var_t.types.find {|t| result = match(s, t) }
result
end
def match_PRegexpType(regexp_t, s)
raise ArgumentError, _("Given Regexp Type has no regular expression") unless regexp_t.pattern
do_match(s, regexp_t.regexp)
end
def match_PPatternType(pattern_t, s)
# Since we want the actual match result (not just a boolean), an iteration over
# Pattern's regular expressions is needed. (They are of PRegexpType)
result = nil
pattern_t.patterns.find {|pattern| result = match(s, pattern) }
result
end
# Returns the first matching entry
def match_Array(array, s)
result = nil
array.flatten.find {|entry| result = match(s, entry) }
result
end
private
def do_match(s, regexp)
result = regexp.match(s)
result.to_a if result
end
end
Copyright 2K16 - 2K18 Indonesian Hacker Rulez