From 9111efc9758f49141886c9c5be3ddf425bc930c9 Mon Sep 17 00:00:00 2001 From: Peter Sprygada Date: Thu, 14 Apr 2016 14:54:03 -0400 Subject: [PATCH] adds two new regex filters for use in playbooks (#14696) The first filter is regex_search which adds the ability to do a regex search on a fact. The filter supports returning either all capture groups or a set of capture groups (either by index or named). Example usage of regex_search filter debug: msg="{{ out.stdout[0] | regex_search('image version. (?P\d+).(\d+)', '\\g', '\\2' ) }}" The second filter is regex_findall with adds the capability to do a regex findall on a fact or variable and return all occurances of a pattern. debug: msg="{{ out.stdout[0] | regex_findall('vlan (\d+)' }}" The filter supports two addtional keyword arguments, ignorecase=[true, false] and multiline=[true, false] --- lib/ansible/plugins/filter/core.py | 41 ++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/lib/ansible/plugins/filter/core.py b/lib/ansible/plugins/filter/core.py index 51638d02ae4..b413dca4ea6 100644 --- a/lib/ansible/plugins/filter/core.py +++ b/lib/ansible/plugins/filter/core.py @@ -138,6 +138,45 @@ def regex_replace(value='', pattern='', replacement='', ignorecase=False): _re = re.compile(pattern, flags=flags) return _re.sub(replacement, value) +def regex_findall(value, regex, multiline=False, ignorecase=False): + ''' Perform re.findall and return the list of matches ''' + flags = 0 + if ignorecase: + flags |= re.I + if multiline: + flags |= re.M + return re.findall(regex, value, flags) + +def regex_search(value, regex, *args, **kwargs): + ''' Perform re.search and return the list of matches or a backref ''' + + groups = list() + for arg in args: + if arg.startswith('\\g'): + match = re.match(r'\\g<(\S+)>', arg).group(1) + groups.append(match) + elif arg.startswith('\\'): + match = int(re.match(r'\\(\d+)', arg).group(1)) + groups.append(match) + else: + raise errors.AnsibleFilterError('Unknown argument') + + flags = 0 + if kwargs.get('ignorecase'): + flags |= re.I + if kwargs.get('multiline'): + flags |= re.M + + match = re.search(regex, value, flags) + if match: + if not groups: + return match.group() + else: + items = list() + for item in groups: + items.append(match.group(item)) + return items + def ternary(value, true_val, false_val): ''' value ? true_val : false_val ''' if value: @@ -414,6 +453,8 @@ class FilterModule(object): # regex 'regex_replace': regex_replace, 'regex_escape': regex_escape, + 'regex_search': regex_search, + 'regex_findall': regex_findall, # ? : ; 'ternary': ternary,