From f194108a261ba015673916c07a76da094aaff3c1 Mon Sep 17 00:00:00 2001 From: Christian Fetzer Date: Wed, 28 Apr 2021 14:45:01 +0200 Subject: [PATCH] docs: Improve documentation for regex_search,replace,findall (#74368) Improve the documentation for regex_search by adding a few more realistic examples such as showing how to extract only parts of a string by using regex groups. Extend regex_findall and regex_replace by an example that includes the multiline and ignorecase parameters. --- .../rst/user_guide/playbooks_filters.rst | 58 ++++++++++++------- 1 file changed, 36 insertions(+), 22 deletions(-) diff --git a/docs/docsite/rst/user_guide/playbooks_filters.rst b/docs/docsite/rst/user_guide/playbooks_filters.rst index a50643c8f45..1f14d7809a4 100644 --- a/docs/docsite/rst/user_guide/playbooks_filters.rst +++ b/docs/docsite/rst/user_guide/playbooks_filters.rst @@ -1485,47 +1485,61 @@ The ``urlsplit`` filter extracts the fragment, hostname, netloc, password, path, Searching strings with regular expressions ------------------------------------------ -To search a string with a regex, use the "regex_search" filter:: +To search in a string or extract parts of a string with a regular expression, use the ``regex_search`` filter:: - # search for "foo" in "foobar" - {{ 'foobar' | regex_search('(foo)') }} - # => "foo" + # Extracts the database name from a string + {{ 'server1/database42' | regex_search('database[0-9]+') }} + # => 'database42' - # will return empty if it cannot find a match - {{ 'ansible' | regex_search('(foobar)') }} - # => "" + # Returns an empty string if it cannot find a match + {{ 'ansible' | regex_search('foobar') }} + # => '' - # case insensitive search in multiline mode - {{ 'foo\nBAR' | regex_search("^bar", multiline=True, ignorecase=True) }} + # Example for a case insensitive search in multiline mode + {{ 'foo\nBAR' | regex_search('^bar', multiline=True, ignorecase=True) }} + # => 'BAR' + + # Extracts server and database id from a string + {{ 'server1/database42' | regex_search('server([0-9]+)/database([0-9]+)', '\\1', '\\2') }} + # => ['1', '42'] + + # Extracts dividend and divisor from a division + {{ '21/42' | regex_search('(?P[0-9]+)/(?P[0-9]+)', '\\g', '\\g') }} + # => ['21', '42'] -To search for all occurrences of regex matches, use the "regex_findall" filter:: +To extract all occurrences of regex matches in a string, use the ``regex_findall`` filter:: - # Return a list of all IPv4 addresses in the string + # Returns a list of all IPv4 addresses in the string {{ 'Some DNS servers are 8.8.8.8 and 8.8.4.4' | regex_findall('\\b(?:[0-9]{1,3}\\.){3}[0-9]{1,3}\\b') }} + # => ['8.8.8.8', '8.8.4.4'] + + # Returns all lines that end with "ar" + {{ 'CAR\ntar\nfoo\nbar\n' | regex_findall('^.ar$', multiline=True, ignorecase=True) }} + # => ['CAR', 'tar', 'bar'] -To replace text in a string with regex, use the "regex_replace" filter:: +To replace text in a string with regex, use the ``regex_replace`` filter:: - # convert "ansible" to "able" + # Convert "ansible" to "able" {{ 'ansible' | regex_replace('^a.*i(.*)$', 'a\\1') }} # => 'able' - # convert "foobar" to "bar" + # Convert "foobar" to "bar" {{ 'foobar' | regex_replace('^f.*o(.*)$', '\\1') }} # => 'bar' - # convert "localhost:80" to "localhost, 80" using named groups + # Convert "localhost:80" to "localhost, 80" using named groups {{ 'localhost:80' | regex_replace('^(?P.+):(?P\\d+)$', '\\g, \\g') }} # => 'localhost, 80' - # convert "localhost:80" to "localhost" + # Convert "localhost:80" to "localhost" {{ 'localhost:80' | regex_replace(':80') }} # => 'localhost' - # change a multiline string - {{ 'var' | regex_replace('^', '#CommentThis#', multiline=True) }} - # => '#CommentThis#var' + # Comment all lines that end with "ar" + {{ 'CAR\ntar\nfoo\nbar\n' | regex_replace('^(.ar)$', '#\\1', multiline=True, ignorecase=True) }} + # => '#CAR\n#tar\nfoo\n#bar\n' .. note:: If you want to match the whole string and you are using ``*`` make sure to always wraparound your regular expression with the start/end anchors. For example ``^(.*)$`` will always match only one result, while ``(.*)`` on some Python versions will match the whole string and an empty string at the end, which means it will make two replacements:: @@ -1549,18 +1563,18 @@ To replace text in a string with regex, use the "regex_replace" filter:: {{ hosts | map('regex_replace', '(.*)', '\\1:80') | list }} .. note:: - Prior to ansible 2.0, if "regex_replace" filter was used with variables inside YAML arguments (as opposed to simpler 'key=value' arguments), then you needed to escape backreferences (for example, ``\\1``) with 4 backslashes (``\\\\``) instead of 2 (``\\``). + Prior to ansible 2.0, if ``regex_replace`` filter was used with variables inside YAML arguments (as opposed to simpler 'key=value' arguments), then you needed to escape backreferences (for example, ``\\1``) with 4 backslashes (``\\\\``) instead of 2 (``\\``). .. versionadded:: 2.0 -To escape special characters within a standard Python regex, use the "regex_escape" filter (using the default re_type='python' option):: +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:: +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') }}