Repository: commons-lang Updated Branches: refs/heads/master 849578d3a -> a6addf94e
LANG-1139: Add null safe methods in StringUtils to replace by regular expression : - StringUtils.replaceAll(String, String, String) - StringUtils.replaceFirst(String, String, String) Project: http://git-wip-us.apache.org/repos/asf/commons-lang/repo Commit: http://git-wip-us.apache.org/repos/asf/commons-lang/commit/3acffccf Tree: http://git-wip-us.apache.org/repos/asf/commons-lang/tree/3acffccf Diff: http://git-wip-us.apache.org/repos/asf/commons-lang/diff/3acffccf Branch: refs/heads/master Commit: 3acffccf15027bcf87e25a432f085c45e103b0ec Parents: 0343b4f Author: Loic Guibert <lfdummy-apa...@yahoo.fr> Authored: Thu May 28 16:20:14 2015 +0400 Committer: Loic Guibert <lfdummy-apa...@yahoo.fr> Committed: Thu May 28 16:20:14 2015 +0400 ---------------------------------------------------------------------- .../org/apache/commons/lang3/StringUtils.java | 104 +++++++++++++++++++ .../apache/commons/lang3/StringUtilsTest.java | 57 ++++++++++ 2 files changed, 161 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/commons-lang/blob/3acffccf/src/main/java/org/apache/commons/lang3/StringUtils.java ---------------------------------------------------------------------- diff --git a/src/main/java/org/apache/commons/lang3/StringUtils.java b/src/main/java/org/apache/commons/lang3/StringUtils.java index 29d7098..b91d3b8 100644 --- a/src/main/java/org/apache/commons/lang3/StringUtils.java +++ b/src/main/java/org/apache/commons/lang3/StringUtils.java @@ -25,6 +25,7 @@ import java.util.Iterator; import java.util.List; import java.util.Locale; import java.util.regex.Pattern; +import java.util.regex.PatternSyntaxException; /** * <p>Operations on {@link java.lang.String} that are @@ -4530,6 +4531,109 @@ public class StringUtils { } /** + * <p>Replaces each substring of the text String that matches the given regular expression + * with the given replacement.</p> + * + * This method is a {@code null} safe equivalent to: + * <ul> + * <li>{@code text.replaceAll(regex, replacement)}</li> + * <li>{@code Pattern.compile(regex).matcher(text).replaceAll(replacement)}</li> + * </ul> + * + * <p>A {@code null} reference passed to this method is a no-op.</p> + * + * <p>Unlike in the {@link #replacePattern(String, String, String)} method, the {@link Pattern#DOTALL} option + * is NOT automatically added. + * To use the DOTALL option prepend <code>"(?s)"</code> to the regex. + * DOTALL is also know as single-line mode in Perl.</p> + * + * <pre> + * StringUtils.replaceAll(null, *, *) = null + * StringUtils.replaceAll("any", null, *) = "any" + * StringUtils.replaceAll("any", *, null) = "any" + * StringUtils.replaceAll("", "", "zzz") = "zzz" + * StringUtils.replaceAll("", ".*", "zzz") = "zzz" + * StringUtils.replaceAll("", ".+", "zzz") = "" + * StringUtils.replaceAll("<__>\n<__>", "<.*>", "z") = "z\nz" + * StringUtils.replaceAll("<__>\n<__>", "(?s)<.*>", "z") = "z" + * StringUtils.replaceAll("ABCabc123", "[a-z]", "_") = "ABC___123" + * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123" + * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "") = "ABC123" + * StringUtils.replaceAll("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit" + * </pre> + * + * @param text text to search and replace in, may be null + * @param regex the regular expression to which this string is to be matched + * @param replacement the string to be substituted for each match + * @return the text with any replacements processed, + * {@code null} if null String input + * + * @throws PatternSyntaxException + * if the regular expression's syntax is invalid + * + * @see String#replaceAll(String, String) + * @see java.util.regex.Pattern + * @see java.util.regex.Pattern#DOTALL + */ + public static String replaceAll(final String text, final String regex, final String replacement) { + if (text == null || regex == null|| replacement == null ) { + return text; + } + return text.replaceAll(regex, replacement); + } + + /** + * <p>Replaces the first substring of the text string that matches the given regular expression + * with the given replacement.</p> + * + * This method is a {@code null} safe equivalent to: + * <ul> + * <li>{@code text.replaceFirst(regex, replacement)}</li> + * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(replacement)}</li> + * </ul> + * + * <p>A {@code null} reference passed to this method is a no-op.</p> + * + * <p>The {@link Pattern#DOTALL} option is NOT automatically added. + * To use the DOTALL option prepend <code>"(?s)"</code> to the regex. + * DOTALL is also know as single-line mode in Perl.</p> + * + * <pre> + * StringUtils.replaceFirst(null, *, *) = null + * StringUtils.replaceFirst("any", null, *) = "any" + * StringUtils.replaceFirst("any", *, null) = "any" + * StringUtils.replaceFirst("", "", "zzz") = "zzz" + * StringUtils.replaceFirst("", ".*", "zzz") = "zzz" + * StringUtils.replaceFirst("", ".+", "zzz") = "" + * StringUtils.replaceFirst("<__>\n<__>", "<.*>", "z") = "z\n<__>" + * StringUtils.replaceFirst("<__>\n<__>", "(?s)<.*>", "z") = "z" + * StringUtils.replaceFirst("ABCabc123", "[a-z]", "_") = "ABC_bc123" + * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_") = "ABC_123abc" + * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "") = "ABC123abc" + * StringUtils.replaceFirst("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum dolor sit" + * </pre> + * + * @param text text to search and replace in, may be null + * @param regex the regular expression to which this string is to be matched + * @param replacement the string to be substituted for the first match + * @return the text with the first replacement processed, + * {@code null} if null String input + * + * @throws PatternSyntaxException + * if the regular expression's syntax is invalid + * + * @see String#replaceFirst(String, String) + * @see java.util.regex.Pattern + * @see java.util.regex.Pattern#DOTALL + */ + public static String replaceFirst(final String text, final String regex, final String replacement) { + if (text == null || regex == null|| replacement == null ) { + return text; + } + return text.replaceFirst(regex, replacement); + } + + /** * <p>Replaces all occurrences of a String within another String.</p> * * <p>A {@code null} reference passed to this method is a no-op.</p> http://git-wip-us.apache.org/repos/asf/commons-lang/blob/3acffccf/src/test/java/org/apache/commons/lang3/StringUtilsTest.java ---------------------------------------------------------------------- diff --git a/src/test/java/org/apache/commons/lang3/StringUtilsTest.java b/src/test/java/org/apache/commons/lang3/StringUtilsTest.java index a83eed6..40e4217 100644 --- a/src/test/java/org/apache/commons/lang3/StringUtilsTest.java +++ b/src/test/java/org/apache/commons/lang3/StringUtilsTest.java @@ -35,6 +35,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.Iterator; import java.util.Locale; +import java.util.regex.PatternSyntaxException; import org.apache.commons.lang3.text.WordUtils; import org.junit.Test; @@ -1175,6 +1176,62 @@ public class StringUtilsTest { } @Test + public void testReplaceAll_StringStringString() { + assertNull(StringUtils.replaceAll(null, "", "")); + + assertEquals("any", StringUtils.replaceAll("any", null, "")); + assertEquals("any", StringUtils.replaceAll("any", "", null)); + + assertEquals("zzz", StringUtils.replaceAll("", "", "zzz")); + assertEquals("zzz", StringUtils.replaceAll("", ".*", "zzz")); + assertEquals("", StringUtils.replaceAll("", ".+", "zzz")); + + assertEquals("z\nz", StringUtils.replaceAll("<__>\n<__>", "<.*>", "z")); + assertEquals("z", StringUtils.replaceAll("<__>\n<__>", "(?s)<.*>", "z")); + + assertEquals("ABC___123", StringUtils.replaceAll("ABCabc123", "[a-z]", "_")); + assertEquals("ABC_123", StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "_")); + assertEquals("ABC123", StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "")); + assertEquals("Lorem_ipsum_dolor_sit", + StringUtils.replaceAll("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2")); + + try { + StringUtils.replaceAll("any", "{badRegexSyntax}", ""); + fail("StringUtils.replaceAll expecting PatternSyntaxException"); + } catch (final PatternSyntaxException ex) { + // empty + } + } + + @Test + public void testReplaceFirst_StringStringString() { + assertNull(StringUtils.replaceFirst(null, "", "")); + + assertEquals("any", StringUtils.replaceFirst("any", null, "")); + assertEquals("any", StringUtils.replaceFirst("any", "", null)); + + assertEquals("zzz", StringUtils.replaceFirst("", "", "zzz")); + assertEquals("zzz", StringUtils.replaceFirst("", ".*", "zzz")); + assertEquals("", StringUtils.replaceFirst("", ".+", "zzz")); + + assertEquals("z\n<__>", StringUtils.replaceFirst("<__>\n<__>", "<.*>", "z")); + assertEquals("z", StringUtils.replaceFirst("<__>\n<__>", "(?s)<.*>", "z")); + + assertEquals("ABC_bc123", StringUtils.replaceFirst("ABCabc123", "[a-z]", "_")); + assertEquals("ABC_123abc", StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_")); + assertEquals("ABC123abc", StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "")); + assertEquals("Lorem_ipsum dolor sit", + StringUtils.replaceFirst("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2")); + + try { + StringUtils.replaceFirst("any", "{badRegexSyntax}", ""); + fail("StringUtils.replaceFirst expecting PatternSyntaxException"); + } catch (final PatternSyntaxException ex) { + // empty + } + } + + @Test public void testReplace_StringStringStringInt() { assertNull(StringUtils.replace(null, null, null, 2)); assertNull(StringUtils.replace(null, null, "any", 2));