diff --git a/changelogs/fragments/regex-escape-basic.yaml b/changelogs/fragments/regex-escape-basic.yaml new file mode 100644 index 0000000000..6732b9e8f4 --- /dev/null +++ b/changelogs/fragments/regex-escape-basic.yaml @@ -0,0 +1,8 @@ +minor_changes: +- | + regex_escape - added re_type option to enable escaping POSIX BRE chars + + This distinction is necessary because escaping non-special chars such as + '(' or '{' turns them into special chars, the opposite of what is intended + by using regex_escape on strings being passed as a Basic Regular + Expression. diff --git a/docs/docsite/rst/user_guide/playbooks_filters.rst b/docs/docsite/rst/user_guide/playbooks_filters.rst index ab0a5f3f18..6b55c0d48f 100644 --- a/docs/docsite/rst/user_guide/playbooks_filters.rst +++ b/docs/docsite/rst/user_guide/playbooks_filters.rst @@ -1075,11 +1075,18 @@ To replace text in a string with regex, use the "regex_replace" filter:: .. versionadded:: 2.0 -To escape special characters within a regex, use the "regex_escape" filter:: +To escape special characters within a standard python regex, use the "regex_escape" filter (using the default re_type='python' option):: # convert '^f.*o(.*)$' to '\^f\.\*o\(\.\*\)\$' {{ '^f.*o(.*)$' | regex_escape() }} +.. versionadded:: 2.8 + +To escape special characters within a POSIX basic regex, use the "regex_escape" filter with the re_type='posix_basic' option:: + + # convert '^f.*o(.*)$' to '\^f\.\*o(\.\*)\$' + {{ '^f.*o(.*)$' | regex_escape('posix_basic') }} + Kubernetes Filters `````````````````` diff --git a/lib/ansible/plugins/filter/core.py b/lib/ansible/plugins/filter/core.py index 98885b2409..ac66dcdd97 100644 --- a/lib/ansible/plugins/filter/core.py +++ b/lib/ansible/plugins/filter/core.py @@ -185,9 +185,22 @@ def ternary(value, true_val, false_val, none_val=None): return false_val -def regex_escape(string): +def regex_escape(string, re_type='python'): '''Escape all regular expressions special characters from STRING.''' - return re.escape(string) + if re_type == 'python': + return re.escape(string) + elif re_type == 'posix_basic': + # list of BRE special chars: + # https://en.wikibooks.org/wiki/Regular_Expressions/POSIX_Basic_Regular_Expressions + return regex_replace(string, r'([].[^$*\\])', r'\\\1') + # TODO: implement posix_extended + # It's similar to, but different from python regex, which is similar to, + # but different from PCRE. It's possible that re.escape would work here. + # https://remram44.github.io/regex-cheatsheet/regex.html#programs + elif re_type == 'posix_extended': + raise AnsibleFilterError('Regex type (%s) not yet implemented' % re_type) + else: + raise AnsibleFilterError('Invalid regex type (%s)' % re_type) def from_yaml(data):