RegExUtils.java

  1. /*
  2.  * Licensed to the Apache Software Foundation (ASF) under one or more
  3.  * contributor license agreements.  See the NOTICE file distributed with
  4.  * this work for additional information regarding copyright ownership.
  5.  * The ASF licenses this file to You under the Apache License, Version 2.0
  6.  * (the "License"); you may not use this file except in compliance with
  7.  * the License.  You may obtain a copy of the License at
  8.  *
  9.  *      https://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.apache.commons.lang3;

  18. import java.util.Objects;
  19. import java.util.regex.Matcher;
  20. import java.util.regex.Pattern;

  21. /**
  22.  * Helpers to process Strings using regular expressions.
  23.  *
  24.  * @see java.util.regex.Pattern
  25.  * @since 3.8
  26.  */
  27. public class RegExUtils {

  28.     /**
  29.      * Compiles the given regular expression into a pattern with the {@link Pattern#DOTALL} flag.
  30.      *
  31.      * @param regex The expression to be compiled
  32.      * @return the given regular expression compiled into a pattern with the {@link Pattern#DOTALL} flag.
  33.      * @since 3.13.0
  34.      */
  35.     public static Pattern dotAll(final String regex) {
  36.         return Pattern.compile(regex, Pattern.DOTALL);
  37.     }

  38.     /**
  39.      * Compiles the given regular expression into a pattern with the {@link Pattern#DOTALL} flag, then creates a matcher that will match the given text against
  40.      * this pattern.
  41.      *
  42.      * @param regex The expression to be compiled.
  43.      * @param text  The character sequence to be matched.
  44.      * @return A new matcher for this pattern.
  45.      * @since 3.18.0
  46.      */
  47.     public static Matcher dotAllMatcher(final String regex, final CharSequence text) {
  48.         return dotAll(regex).matcher(text);
  49.     }

  50.     /**
  51.      * Compiles the given regular expression into a pattern with the {@link Pattern#DOTALL} flag, then creates a matcher that will match the given text against
  52.      * this pattern.
  53.      *
  54.      * @param regex The expression to be compiled.
  55.      * @param text  The character sequence to be matched.
  56.      * @return A new matcher for this pattern.
  57.      * @since 3.13.0
  58.      * @deprecated Use {@link #dotAllMatcher(String, CharSequence)}.
  59.      */
  60.     @Deprecated
  61.     public static Matcher dotAllMatcher(final String regex, final String text) {
  62.         return dotAll(regex).matcher(text);
  63.     }

  64.     /**
  65.      * Removes each substring of the text String that matches the given regular expression pattern.
  66.      *
  67.      * This method is a {@code null} safe equivalent to:
  68.      * <ul>
  69.      *  <li>{@code pattern.matcher(text).replaceAll(StringUtils.EMPTY)}</li>
  70.      * </ul>
  71.      *
  72.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  73.      *
  74.      * <pre>{@code
  75.      * StringUtils.removeAll(null, *)      = null
  76.      * StringUtils.removeAll("any", (Pattern) null)  = "any"
  77.      * StringUtils.removeAll("any", Pattern.compile(""))    = "any"
  78.      * StringUtils.removeAll("any", Pattern.compile(".*"))  = ""
  79.      * StringUtils.removeAll("any", Pattern.compile(".+"))  = ""
  80.      * StringUtils.removeAll("abc", Pattern.compile(".?"))  = ""
  81.      * StringUtils.removeAll("A<__>\n<__>B", Pattern.compile("<.*>"))      = "A\nB"
  82.      * StringUtils.removeAll("A<__>\n<__>B", Pattern.compile("(?s)<.*>"))  = "AB"
  83.      * StringUtils.removeAll("A<__>\n<__>B", Pattern.compile("<.*>", Pattern.DOTALL))  = "AB"
  84.      * StringUtils.removeAll("ABCabc123abc", Pattern.compile("[a-z]"))     = "ABC123"
  85.      * }</pre>
  86.      *
  87.      * @param text  text to remove from, may be null
  88.      * @param regex  the regular expression to which this string is to be matched
  89.      * @return  the text with any removes processed,
  90.      *              {@code null} if null String input
  91.      *
  92.      * @see #replaceAll(CharSequence, Pattern, String)
  93.      * @see java.util.regex.Matcher#replaceAll(String)
  94.      * @see java.util.regex.Pattern
  95.      * @since 3.18.0
  96.      */
  97.     public static String removeAll(final CharSequence text, final Pattern regex) {
  98.         return replaceAll(text, regex, StringUtils.EMPTY);
  99.     }

  100.     /**
  101.      * Removes each substring of the text String that matches the given regular expression pattern.
  102.      *
  103.      * This method is a {@code null} safe equivalent to:
  104.      * <ul>
  105.      *  <li>{@code pattern.matcher(text).replaceAll(StringUtils.EMPTY)}</li>
  106.      * </ul>
  107.      *
  108.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  109.      *
  110.      * <pre>{@code
  111.      * StringUtils.removeAll(null, *)      = null
  112.      * StringUtils.removeAll("any", (Pattern) null)  = "any"
  113.      * StringUtils.removeAll("any", Pattern.compile(""))    = "any"
  114.      * StringUtils.removeAll("any", Pattern.compile(".*"))  = ""
  115.      * StringUtils.removeAll("any", Pattern.compile(".+"))  = ""
  116.      * StringUtils.removeAll("abc", Pattern.compile(".?"))  = ""
  117.      * StringUtils.removeAll("A<__>\n<__>B", Pattern.compile("<.*>"))      = "A\nB"
  118.      * StringUtils.removeAll("A<__>\n<__>B", Pattern.compile("(?s)<.*>"))  = "AB"
  119.      * StringUtils.removeAll("A<__>\n<__>B", Pattern.compile("<.*>", Pattern.DOTALL))  = "AB"
  120.      * StringUtils.removeAll("ABCabc123abc", Pattern.compile("[a-z]"))     = "ABC123"
  121.      * }</pre>
  122.      *
  123.      * @param text  text to remove from, may be null
  124.      * @param regex  the regular expression to which this string is to be matched
  125.      * @return  the text with any removes processed,
  126.      *              {@code null} if null String input
  127.      *
  128.      * @see #replaceAll(CharSequence, Pattern, String)
  129.      * @see java.util.regex.Matcher#replaceAll(String)
  130.      * @see java.util.regex.Pattern
  131.      * @deprecated Use {@link #removeAll(CharSequence, Pattern)}.
  132.      */
  133.     @Deprecated
  134.     public static String removeAll(final String text, final Pattern regex) {
  135.         return replaceAll((CharSequence) text, regex, StringUtils.EMPTY);
  136.     }

  137.     /**
  138.      * Removes each substring of the text String that matches the given regular expression.
  139.      *
  140.      * This method is a {@code null} safe equivalent to:
  141.      * <ul>
  142.      *  <li>{@code text.replaceAll(regex, StringUtils.EMPTY)}</li>
  143.      *  <li>{@code Pattern.compile(regex).matcher(text).replaceAll(StringUtils.EMPTY)}</li>
  144.      * </ul>
  145.      *
  146.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  147.      *
  148.      * <p>Unlike in the {@link #removePattern(CharSequence, String)} method, the {@link Pattern#DOTALL} option
  149.      * is NOT automatically added.
  150.      * To use the DOTALL option prepend {@code "(?s)"} to the regex.
  151.      * DOTALL is also known as single-line mode in Perl.</p>
  152.      *
  153.      * <pre>{@code
  154.      * StringUtils.removeAll(null, *)      = null
  155.      * StringUtils.removeAll("any", (String) null)  = "any"
  156.      * StringUtils.removeAll("any", "")    = "any"
  157.      * StringUtils.removeAll("any", ".*")  = ""
  158.      * StringUtils.removeAll("any", ".+")  = ""
  159.      * StringUtils.removeAll("abc", ".?")  = ""
  160.      * StringUtils.removeAll("A<__>\n<__>B", "<.*>")      = "A\nB"
  161.      * StringUtils.removeAll("A<__>\n<__>B", "(?s)<.*>")  = "AB"
  162.      * StringUtils.removeAll("ABCabc123abc", "[a-z]")     = "ABC123"
  163.      * }</pre>
  164.      *
  165.      * @param text  text to remove from, may be null
  166.      * @param regex  the regular expression to which this string is to be matched
  167.      * @return  the text with any removes processed,
  168.      *              {@code null} if null String input
  169.      *
  170.      * @throws  java.util.regex.PatternSyntaxException
  171.      *              if the regular expression's syntax is invalid
  172.      *
  173.      * @see #replaceAll(String, String, String)
  174.      * @see #removePattern(CharSequence, String)
  175.      * @see String#replaceAll(String, String)
  176.      * @see java.util.regex.Pattern
  177.      * @see java.util.regex.Pattern#DOTALL
  178.      */
  179.     public static String removeAll(final String text, final String regex) {
  180.         return replaceAll(text, regex, StringUtils.EMPTY);
  181.     }

  182.     /**
  183.      * Removes the first substring of the text string that matches the given regular expression pattern.
  184.      *
  185.      * This method is a {@code null} safe equivalent to:
  186.      * <ul>
  187.      *  <li>{@code pattern.matcher(text).replaceFirst(StringUtils.EMPTY)}</li>
  188.      * </ul>
  189.      *
  190.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  191.      *
  192.      * <pre>{@code
  193.      * StringUtils.removeFirst(null, *)      = null
  194.      * StringUtils.removeFirst("any", (Pattern) null)  = "any"
  195.      * StringUtils.removeFirst("any", Pattern.compile(""))    = "any"
  196.      * StringUtils.removeFirst("any", Pattern.compile(".*"))  = ""
  197.      * StringUtils.removeFirst("any", Pattern.compile(".+"))  = ""
  198.      * StringUtils.removeFirst("abc", Pattern.compile(".?"))  = "bc"
  199.      * StringUtils.removeFirst("A<__>\n<__>B", Pattern.compile("<.*>"))      = "A\n<__>B"
  200.      * StringUtils.removeFirst("A<__>\n<__>B", Pattern.compile("(?s)<.*>"))  = "AB"
  201.      * StringUtils.removeFirst("ABCabc123", Pattern.compile("[a-z]"))          = "ABCbc123"
  202.      * StringUtils.removeFirst("ABCabc123abc", Pattern.compile("[a-z]+"))      = "ABC123abc"
  203.      * }</pre>
  204.      *
  205.      * @param text  text to remove from, may be null
  206.      * @param regex  the regular expression pattern to which this string is to be matched
  207.      * @return  the text with the first replacement processed,
  208.      *              {@code null} if null String input
  209.      *
  210.      * @see #replaceFirst(String, Pattern, String)
  211.      * @see java.util.regex.Matcher#replaceFirst(String)
  212.      * @see java.util.regex.Pattern
  213.      * @since 3.18.0
  214.      */
  215.     public static String removeFirst(final CharSequence text, final Pattern regex) {
  216.         return replaceFirst(text, regex, StringUtils.EMPTY);
  217.     }

  218.     /**
  219.      * Removes the first substring of the text string that matches the given regular expression pattern.
  220.      *
  221.      * This method is a {@code null} safe equivalent to:
  222.      * <ul>
  223.      *  <li>{@code pattern.matcher(text).replaceFirst(StringUtils.EMPTY)}</li>
  224.      * </ul>
  225.      *
  226.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  227.      *
  228.      * <pre>{@code
  229.      * StringUtils.removeFirst(null, *)      = null
  230.      * StringUtils.removeFirst("any", (Pattern) null)  = "any"
  231.      * StringUtils.removeFirst("any", Pattern.compile(""))    = "any"
  232.      * StringUtils.removeFirst("any", Pattern.compile(".*"))  = ""
  233.      * StringUtils.removeFirst("any", Pattern.compile(".+"))  = ""
  234.      * StringUtils.removeFirst("abc", Pattern.compile(".?"))  = "bc"
  235.      * StringUtils.removeFirst("A<__>\n<__>B", Pattern.compile("<.*>"))      = "A\n<__>B"
  236.      * StringUtils.removeFirst("A<__>\n<__>B", Pattern.compile("(?s)<.*>"))  = "AB"
  237.      * StringUtils.removeFirst("ABCabc123", Pattern.compile("[a-z]"))          = "ABCbc123"
  238.      * StringUtils.removeFirst("ABCabc123abc", Pattern.compile("[a-z]+"))      = "ABC123abc"
  239.      * }</pre>
  240.      *
  241.      * @param text  text to remove from, may be null
  242.      * @param regex  the regular expression pattern to which this string is to be matched
  243.      * @return  the text with the first replacement processed,
  244.      *              {@code null} if null String input
  245.      *
  246.      * @see #replaceFirst(String, Pattern, String)
  247.      * @see java.util.regex.Matcher#replaceFirst(String)
  248.      * @see java.util.regex.Pattern
  249.      * @deprecated Use {@link #removeFirst(CharSequence, Pattern)}.
  250.      */
  251.     @Deprecated
  252.     public static String removeFirst(final String text, final Pattern regex) {
  253.         return replaceFirst(text, regex, StringUtils.EMPTY);
  254.     }

  255.     /**
  256.      * Removes the first substring of the text string that matches the given regular expression.
  257.      *
  258.      * This method is a {@code null} safe equivalent to:
  259.      * <ul>
  260.      *  <li>{@code text.replaceFirst(regex, StringUtils.EMPTY)}</li>
  261.      *  <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(StringUtils.EMPTY)}</li>
  262.      * </ul>
  263.      *
  264.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  265.      *
  266.      * <p>The {@link Pattern#DOTALL} option is NOT automatically added.
  267.      * To use the DOTALL option prepend {@code "(?s)"} to the regex.
  268.      * DOTALL is also known as single-line mode in Perl.</p>
  269.      *
  270.      * <pre>{@code
  271.      * StringUtils.removeFirst(null, *)      = null
  272.      * StringUtils.removeFirst("any", (String) null)  = "any"
  273.      * StringUtils.removeFirst("any", "")    = "any"
  274.      * StringUtils.removeFirst("any", ".*")  = ""
  275.      * StringUtils.removeFirst("any", ".+")  = ""
  276.      * StringUtils.removeFirst("abc", ".?")  = "bc"
  277.      * StringUtils.removeFirst("A<__>\n<__>B", "<.*>")      = "A\n<__>B"
  278.      * StringUtils.removeFirst("A<__>\n<__>B", "(?s)<.*>")  = "AB"
  279.      * StringUtils.removeFirst("ABCabc123", "[a-z]")          = "ABCbc123"
  280.      * StringUtils.removeFirst("ABCabc123abc", "[a-z]+")      = "ABC123abc"
  281.      * }</pre>
  282.      *
  283.      * @param text  text to remove from, may be null
  284.      * @param regex  the regular expression to which this string is to be matched
  285.      * @return  the text with the first replacement processed,
  286.      *              {@code null} if null String input
  287.      *
  288.      * @throws  java.util.regex.PatternSyntaxException
  289.      *              if the regular expression's syntax is invalid
  290.      *
  291.      * @see #replaceFirst(String, String, String)
  292.      * @see String#replaceFirst(String, String)
  293.      * @see java.util.regex.Pattern
  294.      * @see java.util.regex.Pattern#DOTALL
  295.      */
  296.     public static String removeFirst(final String text, final String regex) {
  297.         return replaceFirst(text, regex, StringUtils.EMPTY);
  298.     }

  299.     /**
  300.      * Removes each substring of the source String that matches the given regular expression using the DOTALL option.
  301.      *
  302.      * This call is a {@code null} safe equivalent to:
  303.      * <ul>
  304.      * <li>{@code text.replaceAll(&quot;(?s)&quot; + regex, StringUtils.EMPTY)}</li>
  305.      * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(text).replaceAll(StringUtils.EMPTY)}</li>
  306.      * </ul>
  307.      *
  308.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  309.      *
  310.      * <pre>{@code
  311.      * StringUtils.removePattern(null, *)       = null
  312.      * StringUtils.removePattern("any", (String) null)   = "any"
  313.      * StringUtils.removePattern("A<__>\n<__>B", "<.*>")  = "AB"
  314.      * StringUtils.removePattern("ABCabc123", "[a-z]")    = "ABC123"
  315.      * }</pre>
  316.      *
  317.      * @param text
  318.      *            the source string
  319.      * @param regex
  320.      *            the regular expression to which this string is to be matched
  321.      * @return The resulting {@link String}
  322.      * @see #replacePattern(CharSequence, String, String)
  323.      * @see String#replaceAll(String, String)
  324.      * @see Pattern#DOTALL
  325.      * @since 3.18.0
  326.      */
  327.     public static String removePattern(final CharSequence text, final String regex) {
  328.         return replacePattern(text, regex, StringUtils.EMPTY);
  329.     }

  330.     /**
  331.      * Removes each substring of the source String that matches the given regular expression using the DOTALL option.
  332.      *
  333.      * This call is a {@code null} safe equivalent to:
  334.      * <ul>
  335.      * <li>{@code text.replaceAll(&quot;(?s)&quot; + regex, StringUtils.EMPTY)}</li>
  336.      * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(text).replaceAll(StringUtils.EMPTY)}</li>
  337.      * </ul>
  338.      *
  339.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  340.      *
  341.      * <pre>{@code
  342.      * StringUtils.removePattern(null, *)       = null
  343.      * StringUtils.removePattern("any", (String) null)   = "any"
  344.      * StringUtils.removePattern("A<__>\n<__>B", "<.*>")  = "AB"
  345.      * StringUtils.removePattern("ABCabc123", "[a-z]")    = "ABC123"
  346.      * }</pre>
  347.      *
  348.      * @param text
  349.      *            the source string
  350.      * @param regex
  351.      *            the regular expression to which this string is to be matched
  352.      * @return The resulting {@link String}
  353.      * @see #replacePattern(CharSequence, String, String)
  354.      * @see String#replaceAll(String, String)
  355.      * @see Pattern#DOTALL
  356.      * @deprecated use {@link #removePattern(CharSequence, String)}.
  357.      */
  358.     @Deprecated
  359.     public static String removePattern(final String text, final String regex) {
  360.         return replacePattern((CharSequence) text, regex, StringUtils.EMPTY);
  361.     }

  362.     /**
  363.      * Replaces each substring of the text String that matches the given regular expression pattern with the given replacement.
  364.      *
  365.      * This method is a {@code null} safe equivalent to:
  366.      * <ul>
  367.      *  <li>{@code pattern.matcher(text).replaceAll(replacement)}</li>
  368.      * </ul>
  369.      *
  370.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  371.      *
  372.      * <pre>{@code
  373.      * StringUtils.replaceAll(null, *, *)       = null
  374.      * StringUtils.replaceAll("any", (Pattern) null, *)   = "any"
  375.      * StringUtils.replaceAll("any", *, null)   = "any"
  376.      * StringUtils.replaceAll("", Pattern.compile(""), "zzz")    = "zzz"
  377.      * StringUtils.replaceAll("", Pattern.compile(".*"), "zzz")  = "zzz"
  378.      * StringUtils.replaceAll("", Pattern.compile(".+"), "zzz")  = ""
  379.      * StringUtils.replaceAll("abc", Pattern.compile(""), "ZZ")  = "ZZaZZbZZcZZ"
  380.      * StringUtils.replaceAll("<__>\n<__>", Pattern.compile("<.*>"), "z")                 = "z\nz"
  381.      * StringUtils.replaceAll("<__>\n<__>", Pattern.compile("<.*>", Pattern.DOTALL), "z") = "z"
  382.      * StringUtils.replaceAll("<__>\n<__>", Pattern.compile("(?s)<.*>"), "z")             = "z"
  383.      * StringUtils.replaceAll("ABCabc123", Pattern.compile("[a-z]"), "_")       = "ABC___123"
  384.      * StringUtils.replaceAll("ABCabc123", Pattern.compile("[^A-Z0-9]+"), "_")  = "ABC_123"
  385.      * StringUtils.replaceAll("ABCabc123", Pattern.compile("[^A-Z0-9]+"), "")   = "ABC123"
  386.      * StringUtils.replaceAll("Lorem ipsum  dolor   sit", Pattern.compile("( +)([a-z]+)"), "_$2")  = "Lorem_ipsum_dolor_sit"
  387.      * }</pre>
  388.      *
  389.      * @param text  text to search and replace in, may be null
  390.      * @param regex  the regular expression pattern to which this string is to be matched
  391.      * @param replacement  the string to be substituted for each match
  392.      * @return  the text with any replacements processed,
  393.      *              {@code null} if null String input
  394.      *
  395.      * @see java.util.regex.Matcher#replaceAll(String)
  396.      * @see java.util.regex.Pattern
  397.      */
  398.     public static String replaceAll(final CharSequence text, final Pattern regex, final String replacement) {
  399.         if (ObjectUtils.anyNull(text, regex, replacement)) {
  400.             return toStringOrNull(text);
  401.         }
  402.         return regex.matcher(text).replaceAll(replacement);
  403.     }

  404.     /**
  405.      * Replaces each substring of the text String that matches the given regular expression pattern with the given replacement.
  406.      *
  407.      * This method is a {@code null} safe equivalent to:
  408.      * <ul>
  409.      *  <li>{@code pattern.matcher(text).replaceAll(replacement)}</li>
  410.      * </ul>
  411.      *
  412.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  413.      *
  414.      * <pre>{@code
  415.      * StringUtils.replaceAll(null, *, *)       = null
  416.      * StringUtils.replaceAll("any", (Pattern) null, *)   = "any"
  417.      * StringUtils.replaceAll("any", *, null)   = "any"
  418.      * StringUtils.replaceAll("", Pattern.compile(""), "zzz")    = "zzz"
  419.      * StringUtils.replaceAll("", Pattern.compile(".*"), "zzz")  = "zzz"
  420.      * StringUtils.replaceAll("", Pattern.compile(".+"), "zzz")  = ""
  421.      * StringUtils.replaceAll("abc", Pattern.compile(""), "ZZ")  = "ZZaZZbZZcZZ"
  422.      * StringUtils.replaceAll("<__>\n<__>", Pattern.compile("<.*>"), "z")                 = "z\nz"
  423.      * StringUtils.replaceAll("<__>\n<__>", Pattern.compile("<.*>", Pattern.DOTALL), "z") = "z"
  424.      * StringUtils.replaceAll("<__>\n<__>", Pattern.compile("(?s)<.*>"), "z")             = "z"
  425.      * StringUtils.replaceAll("ABCabc123", Pattern.compile("[a-z]"), "_")       = "ABC___123"
  426.      * StringUtils.replaceAll("ABCabc123", Pattern.compile("[^A-Z0-9]+"), "_")  = "ABC_123"
  427.      * StringUtils.replaceAll("ABCabc123", Pattern.compile("[^A-Z0-9]+"), "")   = "ABC123"
  428.      * StringUtils.replaceAll("Lorem ipsum  dolor   sit", Pattern.compile("( +)([a-z]+)"), "_$2")  = "Lorem_ipsum_dolor_sit"
  429.      * }</pre>
  430.      *
  431.      * @param text  text to search and replace in, may be null
  432.      * @param regex  the regular expression pattern to which this string is to be matched
  433.      * @param replacement  the string to be substituted for each match
  434.      * @return  the text with any replacements processed,
  435.      *              {@code null} if null String input
  436.      *
  437.      * @see java.util.regex.Matcher#replaceAll(String)
  438.      * @see java.util.regex.Pattern
  439.      * @deprecated Use {@link #replaceAll(CharSequence, Pattern, String)}.
  440.      */
  441.     @Deprecated
  442.     public static String replaceAll(final String text, final Pattern regex, final String replacement) {
  443.         return replaceAll((CharSequence) text, regex, replacement);
  444.     }

  445.     /**
  446.      * Replaces each substring of the text String that matches the given regular expression
  447.      * with the given replacement.
  448.      *
  449.      * This method is a {@code null} safe equivalent to:
  450.      * <ul>
  451.      *  <li>{@code text.replaceAll(regex, replacement)}</li>
  452.      *  <li>{@code Pattern.compile(regex).matcher(text).replaceAll(replacement)}</li>
  453.      * </ul>
  454.      *
  455.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  456.      *
  457.      * <p>Unlike in the {@link #replacePattern(CharSequence, String, String)} method, the {@link Pattern#DOTALL} option
  458.      * is NOT automatically added.
  459.      * To use the DOTALL option prepend {@code "(?s)"} to the regex.
  460.      * DOTALL is also known as single-line mode in Perl.</p>
  461.      *
  462.      * <pre>{@code
  463.      * StringUtils.replaceAll(null, *, *)       = null
  464.      * StringUtils.replaceAll("any", (String) null, *)   = "any"
  465.      * StringUtils.replaceAll("any", *, null)   = "any"
  466.      * StringUtils.replaceAll("", "", "zzz")    = "zzz"
  467.      * StringUtils.replaceAll("", ".*", "zzz")  = "zzz"
  468.      * StringUtils.replaceAll("", ".+", "zzz")  = ""
  469.      * StringUtils.replaceAll("abc", "", "ZZ")  = "ZZaZZbZZcZZ"
  470.      * StringUtils.replaceAll("<__>\n<__>", "<.*>", "z")      = "z\nz"
  471.      * StringUtils.replaceAll("<__>\n<__>", "(?s)<.*>", "z")  = "z"
  472.      * StringUtils.replaceAll("ABCabc123", "[a-z]", "_")       = "ABC___123"
  473.      * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "_")  = "ABC_123"
  474.      * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "")   = "ABC123"
  475.      * StringUtils.replaceAll("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum_dolor_sit"
  476.      * }</pre>
  477.      *
  478.      * @param text  text to search and replace in, may be null
  479.      * @param regex  the regular expression to which this string is to be matched
  480.      * @param replacement  the string to be substituted for each match
  481.      * @return  the text with any replacements processed,
  482.      *              {@code null} if null String input
  483.      *
  484.      * @throws  java.util.regex.PatternSyntaxException
  485.      *              if the regular expression's syntax is invalid
  486.      *
  487.      * @see #replacePattern(String, String, String)
  488.      * @see String#replaceAll(String, String)
  489.      * @see java.util.regex.Pattern
  490.      * @see java.util.regex.Pattern#DOTALL
  491.      */
  492.     public static String replaceAll(final String text, final String regex, final String replacement) {
  493.         if (ObjectUtils.anyNull(text, regex, replacement)) {
  494.             return text;
  495.         }
  496.         return text.replaceAll(regex, replacement);
  497.     }

  498.     /**
  499.      * Replaces the first substring of the text string that matches the given regular expression pattern
  500.      * with the given replacement.
  501.      *
  502.      * This method is a {@code null} safe equivalent to:
  503.      * <ul>
  504.      *  <li>{@code pattern.matcher(text).replaceFirst(replacement)}</li>
  505.      * </ul>
  506.      *
  507.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  508.      *
  509.      * <pre>{@code
  510.      * StringUtils.replaceFirst(null, *, *)       = null
  511.      * StringUtils.replaceFirst("any", (Pattern) null, *)   = "any"
  512.      * StringUtils.replaceFirst("any", *, null)   = "any"
  513.      * StringUtils.replaceFirst("", Pattern.compile(""), "zzz")    = "zzz"
  514.      * StringUtils.replaceFirst("", Pattern.compile(".*"), "zzz")  = "zzz"
  515.      * StringUtils.replaceFirst("", Pattern.compile(".+"), "zzz")  = ""
  516.      * StringUtils.replaceFirst("abc", Pattern.compile(""), "ZZ")  = "ZZabc"
  517.      * StringUtils.replaceFirst("<__>\n<__>", Pattern.compile("<.*>"), "z")      = "z\n<__>"
  518.      * StringUtils.replaceFirst("<__>\n<__>", Pattern.compile("(?s)<.*>"), "z")  = "z"
  519.      * StringUtils.replaceFirst("ABCabc123", Pattern.compile("[a-z]"), "_")          = "ABC_bc123"
  520.      * StringUtils.replaceFirst("ABCabc123abc", Pattern.compile("[^A-Z0-9]+"), "_")  = "ABC_123abc"
  521.      * StringUtils.replaceFirst("ABCabc123abc", Pattern.compile("[^A-Z0-9]+"), "")   = "ABC123abc"
  522.      * StringUtils.replaceFirst("Lorem ipsum  dolor   sit", Pattern.compile("( +)([a-z]+)"), "_$2")  = "Lorem_ipsum  dolor   sit"
  523.      * }</pre>
  524.      *
  525.      * @param text  text to search and replace in, may be null
  526.      * @param regex  the regular expression pattern to which this string is to be matched
  527.      * @param replacement  the string to be substituted for the first match
  528.      * @return  the text with the first replacement processed,
  529.      *              {@code null} if null String input
  530.      *
  531.      * @see java.util.regex.Matcher#replaceFirst(String)
  532.      * @see java.util.regex.Pattern
  533.      * @since 3.18.0
  534.      */
  535.     public static String replaceFirst(final CharSequence text, final Pattern regex, final String replacement) {
  536.         if (text == null || regex == null || replacement == null) {
  537.             return toStringOrNull(text);
  538.         }
  539.         return regex.matcher(text).replaceFirst(replacement);
  540.     }

  541.     /**
  542.      * Replaces the first substring of the text string that matches the given regular expression pattern
  543.      * with the given replacement.
  544.      *
  545.      * This method is a {@code null} safe equivalent to:
  546.      * <ul>
  547.      *  <li>{@code pattern.matcher(text).replaceFirst(replacement)}</li>
  548.      * </ul>
  549.      *
  550.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  551.      *
  552.      * <pre>{@code
  553.      * StringUtils.replaceFirst(null, *, *)       = null
  554.      * StringUtils.replaceFirst("any", (Pattern) null, *)   = "any"
  555.      * StringUtils.replaceFirst("any", *, null)   = "any"
  556.      * StringUtils.replaceFirst("", Pattern.compile(""), "zzz")    = "zzz"
  557.      * StringUtils.replaceFirst("", Pattern.compile(".*"), "zzz")  = "zzz"
  558.      * StringUtils.replaceFirst("", Pattern.compile(".+"), "zzz")  = ""
  559.      * StringUtils.replaceFirst("abc", Pattern.compile(""), "ZZ")  = "ZZabc"
  560.      * StringUtils.replaceFirst("<__>\n<__>", Pattern.compile("<.*>"), "z")      = "z\n<__>"
  561.      * StringUtils.replaceFirst("<__>\n<__>", Pattern.compile("(?s)<.*>"), "z")  = "z"
  562.      * StringUtils.replaceFirst("ABCabc123", Pattern.compile("[a-z]"), "_")          = "ABC_bc123"
  563.      * StringUtils.replaceFirst("ABCabc123abc", Pattern.compile("[^A-Z0-9]+"), "_")  = "ABC_123abc"
  564.      * StringUtils.replaceFirst("ABCabc123abc", Pattern.compile("[^A-Z0-9]+"), "")   = "ABC123abc"
  565.      * StringUtils.replaceFirst("Lorem ipsum  dolor   sit", Pattern.compile("( +)([a-z]+)"), "_$2")  = "Lorem_ipsum  dolor   sit"
  566.      * }</pre>
  567.      *
  568.      * @param text  text to search and replace in, may be null
  569.      * @param regex  the regular expression pattern to which this string is to be matched
  570.      * @param replacement  the string to be substituted for the first match
  571.      * @return  the text with the first replacement processed,
  572.      *              {@code null} if null String input
  573.      *
  574.      * @see java.util.regex.Matcher#replaceFirst(String)
  575.      * @see java.util.regex.Pattern
  576.      * @deprecated Use {@link #replaceFirst(CharSequence, Pattern, String)}.
  577.      */
  578.     @Deprecated
  579.     public static String replaceFirst(final String text, final Pattern regex, final String replacement) {
  580.         return replaceFirst((CharSequence) text, regex, replacement);
  581.     }

  582.     /**
  583.      * Replaces the first substring of the text string that matches the given regular expression
  584.      * with the given replacement.
  585.      *
  586.      * This method is a {@code null} safe equivalent to:
  587.      * <ul>
  588.      *  <li>{@code text.replaceFirst(regex, replacement)}</li>
  589.      *  <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(replacement)}</li>
  590.      * </ul>
  591.      *
  592.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  593.      *
  594.      * <p>The {@link Pattern#DOTALL} option is NOT automatically added.
  595.      * To use the DOTALL option prepend {@code "(?s)"} to the regex.
  596.      * DOTALL is also known as single-line mode in Perl.</p>
  597.      *
  598.      * <pre>{@code
  599.      * StringUtils.replaceFirst(null, *, *)       = null
  600.      * StringUtils.replaceFirst("any", (String) null, *)   = "any"
  601.      * StringUtils.replaceFirst("any", *, null)   = "any"
  602.      * StringUtils.replaceFirst("", "", "zzz")    = "zzz"
  603.      * StringUtils.replaceFirst("", ".*", "zzz")  = "zzz"
  604.      * StringUtils.replaceFirst("", ".+", "zzz")  = ""
  605.      * StringUtils.replaceFirst("abc", "", "ZZ")  = "ZZabc"
  606.      * StringUtils.replaceFirst("<__>\n<__>", "<.*>", "z")      = "z\n<__>"
  607.      * StringUtils.replaceFirst("<__>\n<__>", "(?s)<.*>", "z")  = "z"
  608.      * StringUtils.replaceFirst("ABCabc123", "[a-z]", "_")          = "ABC_bc123"
  609.      * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_")  = "ABC_123abc"
  610.      * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "")   = "ABC123abc"
  611.      * StringUtils.replaceFirst("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum  dolor   sit"
  612.      * }</pre>
  613.      *
  614.      * @param text  text to search and replace in, may be null
  615.      * @param regex  the regular expression to which this string is to be matched
  616.      * @param replacement  the string to be substituted for the first match
  617.      * @return  the text with the first replacement processed,
  618.      *              {@code null} if null String input
  619.      *
  620.      * @throws  java.util.regex.PatternSyntaxException
  621.      *              if the regular expression's syntax is invalid
  622.      *
  623.      * @see String#replaceFirst(String, String)
  624.      * @see java.util.regex.Pattern
  625.      * @see java.util.regex.Pattern#DOTALL
  626.      */
  627.     public static String replaceFirst(final String text, final String regex, final String replacement) {
  628.         if (text == null || regex == null || replacement == null) {
  629.             return text;
  630.         }
  631.         return text.replaceFirst(regex, replacement);
  632.     }

  633.     /**
  634.      * Replaces each substring of the source String that matches the given regular expression with the given
  635.      * replacement using the {@link Pattern#DOTALL} option. DOTALL is also known as single-line mode in Perl.
  636.      *
  637.      * This call is a {@code null} safe equivalent to:
  638.      * <ul>
  639.      * <li>{@code text.replaceAll(&quot;(?s)&quot; + regex, replacement)}</li>
  640.      * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(text).replaceAll(replacement)}</li>
  641.      * </ul>
  642.      *
  643.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  644.      *
  645.      * <pre>{@code
  646.      * StringUtils.replacePattern(null, *, *)       = null
  647.      * StringUtils.replacePattern("any", (String) null, *)   = "any"
  648.      * StringUtils.replacePattern("any", *, null)   = "any"
  649.      * StringUtils.replacePattern("", "", "zzz")    = "zzz"
  650.      * StringUtils.replacePattern("", ".*", "zzz")  = "zzz"
  651.      * StringUtils.replacePattern("", ".+", "zzz")  = ""
  652.      * StringUtils.replacePattern("<__>\n<__>", "<.*>", "z")       = "z"
  653.      * StringUtils.replacePattern("ABCabc123", "[a-z]", "_")       = "ABC___123"
  654.      * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_")  = "ABC_123"
  655.      * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "")   = "ABC123"
  656.      * StringUtils.replacePattern("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum_dolor_sit"
  657.      * }</pre>
  658.      *
  659.      * @param text
  660.      *            the source string
  661.      * @param regex
  662.      *            the regular expression to which this string is to be matched
  663.      * @param replacement
  664.      *            the string to be substituted for each match
  665.      * @return The resulting {@link String}
  666.      * @see #replaceAll(String, String, String)
  667.      * @see String#replaceAll(String, String)
  668.      * @see Pattern#DOTALL
  669.      * @since 3.18.0
  670.      */
  671.     public static String replacePattern(final CharSequence text, final String regex, final String replacement) {
  672.         if (ObjectUtils.anyNull(text, regex, replacement)) {
  673.             return toStringOrNull(text);
  674.         }
  675.         return dotAllMatcher(regex, text).replaceAll(replacement);
  676.     }

  677.     /**
  678.      * Replaces each substring of the source String that matches the given regular expression with the given
  679.      * replacement using the {@link Pattern#DOTALL} option. DOTALL is also known as single-line mode in Perl.
  680.      *
  681.      * This call is a {@code null} safe equivalent to:
  682.      * <ul>
  683.      * <li>{@code text.replaceAll(&quot;(?s)&quot; + regex, replacement)}</li>
  684.      * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(text).replaceAll(replacement)}</li>
  685.      * </ul>
  686.      *
  687.      * <p>A {@code null} reference passed to this method is a no-op.</p>
  688.      *
  689.      * <pre>{@code
  690.      * StringUtils.replacePattern(null, *, *)       = null
  691.      * StringUtils.replacePattern("any", (String) null, *)   = "any"
  692.      * StringUtils.replacePattern("any", *, null)   = "any"
  693.      * StringUtils.replacePattern("", "", "zzz")    = "zzz"
  694.      * StringUtils.replacePattern("", ".*", "zzz")  = "zzz"
  695.      * StringUtils.replacePattern("", ".+", "zzz")  = ""
  696.      * StringUtils.replacePattern("<__>\n<__>", "<.*>", "z")       = "z"
  697.      * StringUtils.replacePattern("ABCabc123", "[a-z]", "_")       = "ABC___123"
  698.      * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_")  = "ABC_123"
  699.      * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "")   = "ABC123"
  700.      * StringUtils.replacePattern("Lorem ipsum  dolor   sit", "( +)([a-z]+)", "_$2")  = "Lorem_ipsum_dolor_sit"
  701.      * }</pre>
  702.      *
  703.      * @param text
  704.      *            the source string
  705.      * @param regex
  706.      *            the regular expression to which this string is to be matched
  707.      * @param replacement
  708.      *            the string to be substituted for each match
  709.      * @return The resulting {@link String}
  710.      * @see #replaceAll(String, String, String)
  711.      * @see String#replaceAll(String, String)
  712.      * @see Pattern#DOTALL
  713.      * @deprecated Use {@link #replacePattern(CharSequence, String, String)}.
  714.      */
  715.     @Deprecated
  716.     public static String replacePattern(final String text, final String regex, final String replacement) {
  717.         return replacePattern((CharSequence) text, regex, replacement);
  718.     }

  719.     private static String toStringOrNull(final CharSequence text) {
  720.         return Objects.toString(text, null);
  721.     }

  722.     /**
  723.      * Make private in 4.0.
  724.      *
  725.      * @deprecated TODO Make private in 4.0.
  726.      */
  727.     @Deprecated
  728.     public RegExUtils() {
  729.         // empty
  730.     }
  731. }