001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * https://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.commons.lang3; 018 019import java.util.Objects; 020import java.util.regex.Matcher; 021import java.util.regex.Pattern; 022 023/** 024 * Helpers to process Strings using regular expressions. 025 * 026 * @see java.util.regex.Pattern 027 * @since 3.8 028 */ 029public class RegExUtils { 030 031 /** 032 * The pattern to split version strings. 033 */ 034 static final Pattern VERSION_SPLIT_PATTERN = Pattern.compile("\\."); 035 036 /** 037 * Compiles the given regular expression into a pattern with the {@link Pattern#DOTALL} flag. 038 * 039 * @param regex The expression to be compiled 040 * @return the given regular expression compiled into a pattern with the {@link Pattern#DOTALL} flag. 041 * @since 3.13.0 042 */ 043 public static Pattern dotAll(final String regex) { 044 return Pattern.compile(regex, Pattern.DOTALL); 045 } 046 047 /** 048 * 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 049 * this pattern. 050 * 051 * @param regex The expression to be compiled. 052 * @param text The character sequence to be matched. 053 * @return A new matcher for this pattern. 054 * @since 3.18.0 055 */ 056 public static Matcher dotAllMatcher(final String regex, final CharSequence text) { 057 return dotAll(regex).matcher(text); 058 } 059 060 /** 061 * 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 062 * this pattern. 063 * 064 * @param regex The expression to be compiled. 065 * @param text The character sequence to be matched. 066 * @return A new matcher for this pattern. 067 * @since 3.13.0 068 * @deprecated Use {@link #dotAllMatcher(String, CharSequence)}. 069 */ 070 @Deprecated 071 public static Matcher dotAllMatcher(final String regex, final String text) { 072 return dotAll(regex).matcher(text); 073 } 074 075 /** 076 * Removes each substring of the text String that matches the given regular expression pattern. 077 * 078 * This method is a {@code null} safe equivalent to: 079 * <ul> 080 * <li>{@code pattern.matcher(text).replaceAll(StringUtils.EMPTY)}</li> 081 * </ul> 082 * 083 * <p>A {@code null} reference passed to this method is a no-op.</p> 084 * 085 * <pre>{@code 086 * StringUtils.removeAll(null, *) = null 087 * StringUtils.removeAll("any", (Pattern) null) = "any" 088 * StringUtils.removeAll("any", Pattern.compile("")) = "any" 089 * StringUtils.removeAll("any", Pattern.compile(".*")) = "" 090 * StringUtils.removeAll("any", Pattern.compile(".+")) = "" 091 * StringUtils.removeAll("abc", Pattern.compile(".?")) = "" 092 * StringUtils.removeAll("A<__>\n<__>B", Pattern.compile("<.*>")) = "A\nB" 093 * StringUtils.removeAll("A<__>\n<__>B", Pattern.compile("(?s)<.*>")) = "AB" 094 * StringUtils.removeAll("A<__>\n<__>B", Pattern.compile("<.*>", Pattern.DOTALL)) = "AB" 095 * StringUtils.removeAll("ABCabc123abc", Pattern.compile("[a-z]")) = "ABC123" 096 * }</pre> 097 * 098 * @param text text to remove from, may be null 099 * @param regex the regular expression to which this string is to be matched 100 * @return the text with any removes processed, 101 * {@code null} if null String input 102 * 103 * @see #replaceAll(CharSequence, Pattern, String) 104 * @see java.util.regex.Matcher#replaceAll(String) 105 * @see java.util.regex.Pattern 106 * @since 3.18.0 107 */ 108 public static String removeAll(final CharSequence text, final Pattern regex) { 109 return replaceAll(text, regex, StringUtils.EMPTY); 110 } 111 112 /** 113 * Removes each substring of the text String that matches the given regular expression pattern. 114 * 115 * This method is a {@code null} safe equivalent to: 116 * <ul> 117 * <li>{@code pattern.matcher(text).replaceAll(StringUtils.EMPTY)}</li> 118 * </ul> 119 * 120 * <p>A {@code null} reference passed to this method is a no-op.</p> 121 * 122 * <pre>{@code 123 * StringUtils.removeAll(null, *) = null 124 * StringUtils.removeAll("any", (Pattern) null) = "any" 125 * StringUtils.removeAll("any", Pattern.compile("")) = "any" 126 * StringUtils.removeAll("any", Pattern.compile(".*")) = "" 127 * StringUtils.removeAll("any", Pattern.compile(".+")) = "" 128 * StringUtils.removeAll("abc", Pattern.compile(".?")) = "" 129 * StringUtils.removeAll("A<__>\n<__>B", Pattern.compile("<.*>")) = "A\nB" 130 * StringUtils.removeAll("A<__>\n<__>B", Pattern.compile("(?s)<.*>")) = "AB" 131 * StringUtils.removeAll("A<__>\n<__>B", Pattern.compile("<.*>", Pattern.DOTALL)) = "AB" 132 * StringUtils.removeAll("ABCabc123abc", Pattern.compile("[a-z]")) = "ABC123" 133 * }</pre> 134 * 135 * @param text text to remove from, may be null 136 * @param regex the regular expression to which this string is to be matched 137 * @return the text with any removes processed, 138 * {@code null} if null String input 139 * 140 * @see #replaceAll(CharSequence, Pattern, String) 141 * @see java.util.regex.Matcher#replaceAll(String) 142 * @see java.util.regex.Pattern 143 * @deprecated Use {@link #removeAll(CharSequence, Pattern)}. 144 */ 145 @Deprecated 146 public static String removeAll(final String text, final Pattern regex) { 147 return replaceAll((CharSequence) text, regex, StringUtils.EMPTY); 148 } 149 150 /** 151 * Removes each substring of the text String that matches the given regular expression. 152 * 153 * This method is a {@code null} safe equivalent to: 154 * <ul> 155 * <li>{@code text.replaceAll(regex, StringUtils.EMPTY)}</li> 156 * <li>{@code Pattern.compile(regex).matcher(text).replaceAll(StringUtils.EMPTY)}</li> 157 * </ul> 158 * 159 * <p>A {@code null} reference passed to this method is a no-op.</p> 160 * 161 * <p>Unlike in the {@link #removePattern(CharSequence, String)} method, the {@link Pattern#DOTALL} option 162 * is NOT automatically added. 163 * To use the DOTALL option prepend {@code "(?s)"} to the regex. 164 * DOTALL is also known as single-line mode in Perl.</p> 165 * 166 * <pre>{@code 167 * StringUtils.removeAll(null, *) = null 168 * StringUtils.removeAll("any", (String) null) = "any" 169 * StringUtils.removeAll("any", "") = "any" 170 * StringUtils.removeAll("any", ".*") = "" 171 * StringUtils.removeAll("any", ".+") = "" 172 * StringUtils.removeAll("abc", ".?") = "" 173 * StringUtils.removeAll("A<__>\n<__>B", "<.*>") = "A\nB" 174 * StringUtils.removeAll("A<__>\n<__>B", "(?s)<.*>") = "AB" 175 * StringUtils.removeAll("ABCabc123abc", "[a-z]") = "ABC123" 176 * }</pre> 177 * 178 * @param text text to remove from, may be null 179 * @param regex the regular expression to which this string is to be matched 180 * @return the text with any removes processed, 181 * {@code null} if null String input 182 * 183 * @throws java.util.regex.PatternSyntaxException 184 * if the regular expression's syntax is invalid 185 * 186 * @see #replaceAll(String, String, String) 187 * @see #removePattern(CharSequence, String) 188 * @see String#replaceAll(String, String) 189 * @see java.util.regex.Pattern 190 * @see java.util.regex.Pattern#DOTALL 191 */ 192 public static String removeAll(final String text, final String regex) { 193 return replaceAll(text, regex, StringUtils.EMPTY); 194 } 195 196 /** 197 * Removes the first substring of the text string that matches the given regular expression pattern. 198 * 199 * This method is a {@code null} safe equivalent to: 200 * <ul> 201 * <li>{@code pattern.matcher(text).replaceFirst(StringUtils.EMPTY)}</li> 202 * </ul> 203 * 204 * <p>A {@code null} reference passed to this method is a no-op.</p> 205 * 206 * <pre>{@code 207 * StringUtils.removeFirst(null, *) = null 208 * StringUtils.removeFirst("any", (Pattern) null) = "any" 209 * StringUtils.removeFirst("any", Pattern.compile("")) = "any" 210 * StringUtils.removeFirst("any", Pattern.compile(".*")) = "" 211 * StringUtils.removeFirst("any", Pattern.compile(".+")) = "" 212 * StringUtils.removeFirst("abc", Pattern.compile(".?")) = "bc" 213 * StringUtils.removeFirst("A<__>\n<__>B", Pattern.compile("<.*>")) = "A\n<__>B" 214 * StringUtils.removeFirst("A<__>\n<__>B", Pattern.compile("(?s)<.*>")) = "AB" 215 * StringUtils.removeFirst("ABCabc123", Pattern.compile("[a-z]")) = "ABCbc123" 216 * StringUtils.removeFirst("ABCabc123abc", Pattern.compile("[a-z]+")) = "ABC123abc" 217 * }</pre> 218 * 219 * @param text text to remove from, may be null 220 * @param regex the regular expression pattern to which this string is to be matched 221 * @return the text with the first replacement processed, 222 * {@code null} if null String input 223 * 224 * @see #replaceFirst(String, Pattern, String) 225 * @see java.util.regex.Matcher#replaceFirst(String) 226 * @see java.util.regex.Pattern 227 * @since 3.18.0 228 */ 229 public static String removeFirst(final CharSequence text, final Pattern regex) { 230 return replaceFirst(text, regex, StringUtils.EMPTY); 231 } 232 233 /** 234 * Removes the first substring of the text string that matches the given regular expression pattern. 235 * 236 * This method is a {@code null} safe equivalent to: 237 * <ul> 238 * <li>{@code pattern.matcher(text).replaceFirst(StringUtils.EMPTY)}</li> 239 * </ul> 240 * 241 * <p>A {@code null} reference passed to this method is a no-op.</p> 242 * 243 * <pre>{@code 244 * StringUtils.removeFirst(null, *) = null 245 * StringUtils.removeFirst("any", (Pattern) null) = "any" 246 * StringUtils.removeFirst("any", Pattern.compile("")) = "any" 247 * StringUtils.removeFirst("any", Pattern.compile(".*")) = "" 248 * StringUtils.removeFirst("any", Pattern.compile(".+")) = "" 249 * StringUtils.removeFirst("abc", Pattern.compile(".?")) = "bc" 250 * StringUtils.removeFirst("A<__>\n<__>B", Pattern.compile("<.*>")) = "A\n<__>B" 251 * StringUtils.removeFirst("A<__>\n<__>B", Pattern.compile("(?s)<.*>")) = "AB" 252 * StringUtils.removeFirst("ABCabc123", Pattern.compile("[a-z]")) = "ABCbc123" 253 * StringUtils.removeFirst("ABCabc123abc", Pattern.compile("[a-z]+")) = "ABC123abc" 254 * }</pre> 255 * 256 * @param text text to remove from, may be null 257 * @param regex the regular expression pattern to which this string is to be matched 258 * @return the text with the first replacement processed, 259 * {@code null} if null String input 260 * 261 * @see #replaceFirst(String, Pattern, String) 262 * @see java.util.regex.Matcher#replaceFirst(String) 263 * @see java.util.regex.Pattern 264 * @deprecated Use {@link #removeFirst(CharSequence, Pattern)}. 265 */ 266 @Deprecated 267 public static String removeFirst(final String text, final Pattern regex) { 268 return replaceFirst(text, regex, StringUtils.EMPTY); 269 } 270 271 /** 272 * Removes the first substring of the text string that matches the given regular expression. 273 * 274 * This method is a {@code null} safe equivalent to: 275 * <ul> 276 * <li>{@code text.replaceFirst(regex, StringUtils.EMPTY)}</li> 277 * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(StringUtils.EMPTY)}</li> 278 * </ul> 279 * 280 * <p>A {@code null} reference passed to this method is a no-op.</p> 281 * 282 * <p>The {@link Pattern#DOTALL} option is NOT automatically added. 283 * To use the DOTALL option prepend {@code "(?s)"} to the regex. 284 * DOTALL is also known as single-line mode in Perl.</p> 285 * 286 * <pre>{@code 287 * StringUtils.removeFirst(null, *) = null 288 * StringUtils.removeFirst("any", (String) null) = "any" 289 * StringUtils.removeFirst("any", "") = "any" 290 * StringUtils.removeFirst("any", ".*") = "" 291 * StringUtils.removeFirst("any", ".+") = "" 292 * StringUtils.removeFirst("abc", ".?") = "bc" 293 * StringUtils.removeFirst("A<__>\n<__>B", "<.*>") = "A\n<__>B" 294 * StringUtils.removeFirst("A<__>\n<__>B", "(?s)<.*>") = "AB" 295 * StringUtils.removeFirst("ABCabc123", "[a-z]") = "ABCbc123" 296 * StringUtils.removeFirst("ABCabc123abc", "[a-z]+") = "ABC123abc" 297 * }</pre> 298 * 299 * @param text text to remove from, may be null 300 * @param regex the regular expression to which this string is to be matched 301 * @return the text with the first replacement processed, 302 * {@code null} if null String input 303 * 304 * @throws java.util.regex.PatternSyntaxException 305 * if the regular expression's syntax is invalid 306 * 307 * @see #replaceFirst(String, String, String) 308 * @see String#replaceFirst(String, String) 309 * @see java.util.regex.Pattern 310 * @see java.util.regex.Pattern#DOTALL 311 */ 312 public static String removeFirst(final String text, final String regex) { 313 return replaceFirst(text, regex, StringUtils.EMPTY); 314 } 315 316 /** 317 * Removes each substring of the source String that matches the given regular expression using the DOTALL option. 318 * 319 * This call is a {@code null} safe equivalent to: 320 * <ul> 321 * <li>{@code text.replaceAll("(?s)" + regex, StringUtils.EMPTY)}</li> 322 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(text).replaceAll(StringUtils.EMPTY)}</li> 323 * </ul> 324 * 325 * <p>A {@code null} reference passed to this method is a no-op.</p> 326 * 327 * <pre>{@code 328 * StringUtils.removePattern(null, *) = null 329 * StringUtils.removePattern("any", (String) null) = "any" 330 * StringUtils.removePattern("A<__>\n<__>B", "<.*>") = "AB" 331 * StringUtils.removePattern("ABCabc123", "[a-z]") = "ABC123" 332 * }</pre> 333 * 334 * @param text 335 * the source string 336 * @param regex 337 * the regular expression to which this string is to be matched 338 * @return The resulting {@link String} 339 * @see #replacePattern(CharSequence, String, String) 340 * @see String#replaceAll(String, String) 341 * @see Pattern#DOTALL 342 * @since 3.18.0 343 */ 344 public static String removePattern(final CharSequence text, final String regex) { 345 return replacePattern(text, regex, StringUtils.EMPTY); 346 } 347 348 /** 349 * Removes each substring of the source String that matches the given regular expression using the DOTALL option. 350 * 351 * This call is a {@code null} safe equivalent to: 352 * <ul> 353 * <li>{@code text.replaceAll("(?s)" + regex, StringUtils.EMPTY)}</li> 354 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(text).replaceAll(StringUtils.EMPTY)}</li> 355 * </ul> 356 * 357 * <p>A {@code null} reference passed to this method is a no-op.</p> 358 * 359 * <pre>{@code 360 * StringUtils.removePattern(null, *) = null 361 * StringUtils.removePattern("any", (String) null) = "any" 362 * StringUtils.removePattern("A<__>\n<__>B", "<.*>") = "AB" 363 * StringUtils.removePattern("ABCabc123", "[a-z]") = "ABC123" 364 * }</pre> 365 * 366 * @param text 367 * the source string 368 * @param regex 369 * the regular expression to which this string is to be matched 370 * @return The resulting {@link String} 371 * @see #replacePattern(CharSequence, String, String) 372 * @see String#replaceAll(String, String) 373 * @see Pattern#DOTALL 374 * @deprecated use {@link #removePattern(CharSequence, String)}. 375 */ 376 @Deprecated 377 public static String removePattern(final String text, final String regex) { 378 return replacePattern((CharSequence) text, regex, StringUtils.EMPTY); 379 } 380 381 /** 382 * Replaces each substring of the text String that matches the given regular expression pattern with the given replacement. 383 * 384 * This method is a {@code null} safe equivalent to: 385 * <ul> 386 * <li>{@code pattern.matcher(text).replaceAll(replacement)}</li> 387 * </ul> 388 * 389 * <p>A {@code null} reference passed to this method is a no-op.</p> 390 * 391 * <pre>{@code 392 * StringUtils.replaceAll(null, *, *) = null 393 * StringUtils.replaceAll("any", (Pattern) null, *) = "any" 394 * StringUtils.replaceAll("any", *, null) = "any" 395 * StringUtils.replaceAll("", Pattern.compile(""), "zzz") = "zzz" 396 * StringUtils.replaceAll("", Pattern.compile(".*"), "zzz") = "zzz" 397 * StringUtils.replaceAll("", Pattern.compile(".+"), "zzz") = "" 398 * StringUtils.replaceAll("abc", Pattern.compile(""), "ZZ") = "ZZaZZbZZcZZ" 399 * StringUtils.replaceAll("<__>\n<__>", Pattern.compile("<.*>"), "z") = "z\nz" 400 * StringUtils.replaceAll("<__>\n<__>", Pattern.compile("<.*>", Pattern.DOTALL), "z") = "z" 401 * StringUtils.replaceAll("<__>\n<__>", Pattern.compile("(?s)<.*>"), "z") = "z" 402 * StringUtils.replaceAll("ABCabc123", Pattern.compile("[a-z]"), "_") = "ABC___123" 403 * StringUtils.replaceAll("ABCabc123", Pattern.compile("[^A-Z0-9]+"), "_") = "ABC_123" 404 * StringUtils.replaceAll("ABCabc123", Pattern.compile("[^A-Z0-9]+"), "") = "ABC123" 405 * StringUtils.replaceAll("Lorem ipsum dolor sit", Pattern.compile("( +)([a-z]+)"), "_$2") = "Lorem_ipsum_dolor_sit" 406 * }</pre> 407 * 408 * @param text text to search and replace in, may be null 409 * @param regex the regular expression pattern to which this string is to be matched 410 * @param replacement the string to be substituted for each match 411 * @return the text with any replacements processed, 412 * {@code null} if null String input 413 * 414 * @see java.util.regex.Matcher#replaceAll(String) 415 * @see java.util.regex.Pattern 416 */ 417 public static String replaceAll(final CharSequence text, final Pattern regex, final String replacement) { 418 if (ObjectUtils.anyNull(text, regex, replacement)) { 419 return toStringOrNull(text); 420 } 421 return regex.matcher(text).replaceAll(replacement); 422 } 423 424 /** 425 * Replaces each substring of the text String that matches the given regular expression pattern with the given replacement. 426 * 427 * This method is a {@code null} safe equivalent to: 428 * <ul> 429 * <li>{@code pattern.matcher(text).replaceAll(replacement)}</li> 430 * </ul> 431 * 432 * <p>A {@code null} reference passed to this method is a no-op.</p> 433 * 434 * <pre>{@code 435 * StringUtils.replaceAll(null, *, *) = null 436 * StringUtils.replaceAll("any", (Pattern) null, *) = "any" 437 * StringUtils.replaceAll("any", *, null) = "any" 438 * StringUtils.replaceAll("", Pattern.compile(""), "zzz") = "zzz" 439 * StringUtils.replaceAll("", Pattern.compile(".*"), "zzz") = "zzz" 440 * StringUtils.replaceAll("", Pattern.compile(".+"), "zzz") = "" 441 * StringUtils.replaceAll("abc", Pattern.compile(""), "ZZ") = "ZZaZZbZZcZZ" 442 * StringUtils.replaceAll("<__>\n<__>", Pattern.compile("<.*>"), "z") = "z\nz" 443 * StringUtils.replaceAll("<__>\n<__>", Pattern.compile("<.*>", Pattern.DOTALL), "z") = "z" 444 * StringUtils.replaceAll("<__>\n<__>", Pattern.compile("(?s)<.*>"), "z") = "z" 445 * StringUtils.replaceAll("ABCabc123", Pattern.compile("[a-z]"), "_") = "ABC___123" 446 * StringUtils.replaceAll("ABCabc123", Pattern.compile("[^A-Z0-9]+"), "_") = "ABC_123" 447 * StringUtils.replaceAll("ABCabc123", Pattern.compile("[^A-Z0-9]+"), "") = "ABC123" 448 * StringUtils.replaceAll("Lorem ipsum dolor sit", Pattern.compile("( +)([a-z]+)"), "_$2") = "Lorem_ipsum_dolor_sit" 449 * }</pre> 450 * 451 * @param text text to search and replace in, may be null 452 * @param regex the regular expression pattern to which this string is to be matched 453 * @param replacement the string to be substituted for each match 454 * @return the text with any replacements processed, 455 * {@code null} if null String input 456 * 457 * @see java.util.regex.Matcher#replaceAll(String) 458 * @see java.util.regex.Pattern 459 * @deprecated Use {@link #replaceAll(CharSequence, Pattern, String)}. 460 */ 461 @Deprecated 462 public static String replaceAll(final String text, final Pattern regex, final String replacement) { 463 return replaceAll((CharSequence) text, regex, replacement); 464 } 465 466 /** 467 * Replaces each substring of the text String that matches the given regular expression 468 * with the given replacement. 469 * 470 * This method is a {@code null} safe equivalent to: 471 * <ul> 472 * <li>{@code text.replaceAll(regex, replacement)}</li> 473 * <li>{@code Pattern.compile(regex).matcher(text).replaceAll(replacement)}</li> 474 * </ul> 475 * 476 * <p>A {@code null} reference passed to this method is a no-op.</p> 477 * 478 * <p>Unlike in the {@link #replacePattern(CharSequence, String, String)} method, the {@link Pattern#DOTALL} option 479 * is NOT automatically added. 480 * To use the DOTALL option prepend {@code "(?s)"} to the regex. 481 * DOTALL is also known as single-line mode in Perl.</p> 482 * 483 * <pre>{@code 484 * StringUtils.replaceAll(null, *, *) = null 485 * StringUtils.replaceAll("any", (String) null, *) = "any" 486 * StringUtils.replaceAll("any", *, null) = "any" 487 * StringUtils.replaceAll("", "", "zzz") = "zzz" 488 * StringUtils.replaceAll("", ".*", "zzz") = "zzz" 489 * StringUtils.replaceAll("", ".+", "zzz") = "" 490 * StringUtils.replaceAll("abc", "", "ZZ") = "ZZaZZbZZcZZ" 491 * StringUtils.replaceAll("<__>\n<__>", "<.*>", "z") = "z\nz" 492 * StringUtils.replaceAll("<__>\n<__>", "(?s)<.*>", "z") = "z" 493 * StringUtils.replaceAll("ABCabc123", "[a-z]", "_") = "ABC___123" 494 * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123" 495 * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "") = "ABC123" 496 * StringUtils.replaceAll("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit" 497 * }</pre> 498 * 499 * @param text text to search and replace in, may be null 500 * @param regex the regular expression to which this string is to be matched 501 * @param replacement the string to be substituted for each match 502 * @return the text with any replacements processed, 503 * {@code null} if null String input 504 * 505 * @throws java.util.regex.PatternSyntaxException 506 * if the regular expression's syntax is invalid 507 * 508 * @see #replacePattern(String, String, String) 509 * @see String#replaceAll(String, String) 510 * @see java.util.regex.Pattern 511 * @see java.util.regex.Pattern#DOTALL 512 */ 513 public static String replaceAll(final String text, final String regex, final String replacement) { 514 if (ObjectUtils.anyNull(text, regex, replacement)) { 515 return text; 516 } 517 return text.replaceAll(regex, replacement); 518 } 519 520 /** 521 * Replaces the first substring of the text string that matches the given regular expression pattern 522 * with the given replacement. 523 * 524 * This method is a {@code null} safe equivalent to: 525 * <ul> 526 * <li>{@code pattern.matcher(text).replaceFirst(replacement)}</li> 527 * </ul> 528 * 529 * <p>A {@code null} reference passed to this method is a no-op.</p> 530 * 531 * <pre>{@code 532 * StringUtils.replaceFirst(null, *, *) = null 533 * StringUtils.replaceFirst("any", (Pattern) null, *) = "any" 534 * StringUtils.replaceFirst("any", *, null) = "any" 535 * StringUtils.replaceFirst("", Pattern.compile(""), "zzz") = "zzz" 536 * StringUtils.replaceFirst("", Pattern.compile(".*"), "zzz") = "zzz" 537 * StringUtils.replaceFirst("", Pattern.compile(".+"), "zzz") = "" 538 * StringUtils.replaceFirst("abc", Pattern.compile(""), "ZZ") = "ZZabc" 539 * StringUtils.replaceFirst("<__>\n<__>", Pattern.compile("<.*>"), "z") = "z\n<__>" 540 * StringUtils.replaceFirst("<__>\n<__>", Pattern.compile("(?s)<.*>"), "z") = "z" 541 * StringUtils.replaceFirst("ABCabc123", Pattern.compile("[a-z]"), "_") = "ABC_bc123" 542 * StringUtils.replaceFirst("ABCabc123abc", Pattern.compile("[^A-Z0-9]+"), "_") = "ABC_123abc" 543 * StringUtils.replaceFirst("ABCabc123abc", Pattern.compile("[^A-Z0-9]+"), "") = "ABC123abc" 544 * StringUtils.replaceFirst("Lorem ipsum dolor sit", Pattern.compile("( +)([a-z]+)"), "_$2") = "Lorem_ipsum dolor sit" 545 * }</pre> 546 * 547 * @param text text to search and replace in, may be null 548 * @param regex the regular expression pattern to which this string is to be matched 549 * @param replacement the string to be substituted for the first match 550 * @return the text with the first replacement processed, 551 * {@code null} if null String input 552 * 553 * @see java.util.regex.Matcher#replaceFirst(String) 554 * @see java.util.regex.Pattern 555 * @since 3.18.0 556 */ 557 public static String replaceFirst(final CharSequence text, final Pattern regex, final String replacement) { 558 if (text == null || regex == null || replacement == null) { 559 return toStringOrNull(text); 560 } 561 return regex.matcher(text).replaceFirst(replacement); 562 } 563 564 /** 565 * Replaces the first substring of the text string that matches the given regular expression pattern 566 * with the given replacement. 567 * 568 * This method is a {@code null} safe equivalent to: 569 * <ul> 570 * <li>{@code pattern.matcher(text).replaceFirst(replacement)}</li> 571 * </ul> 572 * 573 * <p>A {@code null} reference passed to this method is a no-op.</p> 574 * 575 * <pre>{@code 576 * StringUtils.replaceFirst(null, *, *) = null 577 * StringUtils.replaceFirst("any", (Pattern) null, *) = "any" 578 * StringUtils.replaceFirst("any", *, null) = "any" 579 * StringUtils.replaceFirst("", Pattern.compile(""), "zzz") = "zzz" 580 * StringUtils.replaceFirst("", Pattern.compile(".*"), "zzz") = "zzz" 581 * StringUtils.replaceFirst("", Pattern.compile(".+"), "zzz") = "" 582 * StringUtils.replaceFirst("abc", Pattern.compile(""), "ZZ") = "ZZabc" 583 * StringUtils.replaceFirst("<__>\n<__>", Pattern.compile("<.*>"), "z") = "z\n<__>" 584 * StringUtils.replaceFirst("<__>\n<__>", Pattern.compile("(?s)<.*>"), "z") = "z" 585 * StringUtils.replaceFirst("ABCabc123", Pattern.compile("[a-z]"), "_") = "ABC_bc123" 586 * StringUtils.replaceFirst("ABCabc123abc", Pattern.compile("[^A-Z0-9]+"), "_") = "ABC_123abc" 587 * StringUtils.replaceFirst("ABCabc123abc", Pattern.compile("[^A-Z0-9]+"), "") = "ABC123abc" 588 * StringUtils.replaceFirst("Lorem ipsum dolor sit", Pattern.compile("( +)([a-z]+)"), "_$2") = "Lorem_ipsum dolor sit" 589 * }</pre> 590 * 591 * @param text text to search and replace in, may be null 592 * @param regex the regular expression pattern to which this string is to be matched 593 * @param replacement the string to be substituted for the first match 594 * @return the text with the first replacement processed, 595 * {@code null} if null String input 596 * 597 * @see java.util.regex.Matcher#replaceFirst(String) 598 * @see java.util.regex.Pattern 599 * @deprecated Use {@link #replaceFirst(CharSequence, Pattern, String)}. 600 */ 601 @Deprecated 602 public static String replaceFirst(final String text, final Pattern regex, final String replacement) { 603 return replaceFirst((CharSequence) text, regex, replacement); 604 } 605 606 /** 607 * Replaces the first substring of the text string that matches the given regular expression 608 * with the given replacement. 609 * 610 * This method is a {@code null} safe equivalent to: 611 * <ul> 612 * <li>{@code text.replaceFirst(regex, replacement)}</li> 613 * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(replacement)}</li> 614 * </ul> 615 * 616 * <p>A {@code null} reference passed to this method is a no-op.</p> 617 * 618 * <p>The {@link Pattern#DOTALL} option is NOT automatically added. 619 * To use the DOTALL option prepend {@code "(?s)"} to the regex. 620 * DOTALL is also known as single-line mode in Perl.</p> 621 * 622 * <pre>{@code 623 * StringUtils.replaceFirst(null, *, *) = null 624 * StringUtils.replaceFirst("any", (String) null, *) = "any" 625 * StringUtils.replaceFirst("any", *, null) = "any" 626 * StringUtils.replaceFirst("", "", "zzz") = "zzz" 627 * StringUtils.replaceFirst("", ".*", "zzz") = "zzz" 628 * StringUtils.replaceFirst("", ".+", "zzz") = "" 629 * StringUtils.replaceFirst("abc", "", "ZZ") = "ZZabc" 630 * StringUtils.replaceFirst("<__>\n<__>", "<.*>", "z") = "z\n<__>" 631 * StringUtils.replaceFirst("<__>\n<__>", "(?s)<.*>", "z") = "z" 632 * StringUtils.replaceFirst("ABCabc123", "[a-z]", "_") = "ABC_bc123" 633 * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_") = "ABC_123abc" 634 * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "") = "ABC123abc" 635 * StringUtils.replaceFirst("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum dolor sit" 636 * }</pre> 637 * 638 * @param text text to search and replace in, may be null 639 * @param regex the regular expression to which this string is to be matched 640 * @param replacement the string to be substituted for the first match 641 * @return the text with the first replacement processed, 642 * {@code null} if null String input 643 * 644 * @throws java.util.regex.PatternSyntaxException 645 * if the regular expression's syntax is invalid 646 * 647 * @see String#replaceFirst(String, String) 648 * @see java.util.regex.Pattern 649 * @see java.util.regex.Pattern#DOTALL 650 */ 651 public static String replaceFirst(final String text, final String regex, final String replacement) { 652 if (text == null || regex == null || replacement == null) { 653 return text; 654 } 655 return text.replaceFirst(regex, replacement); 656 } 657 658 /** 659 * Replaces each substring of the source String that matches the given regular expression with the given 660 * replacement using the {@link Pattern#DOTALL} option. DOTALL is also known as single-line mode in Perl. 661 * 662 * This call is a {@code null} safe equivalent to: 663 * <ul> 664 * <li>{@code text.replaceAll("(?s)" + regex, replacement)}</li> 665 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(text).replaceAll(replacement)}</li> 666 * </ul> 667 * 668 * <p>A {@code null} reference passed to this method is a no-op.</p> 669 * 670 * <pre>{@code 671 * StringUtils.replacePattern(null, *, *) = null 672 * StringUtils.replacePattern("any", (String) null, *) = "any" 673 * StringUtils.replacePattern("any", *, null) = "any" 674 * StringUtils.replacePattern("", "", "zzz") = "zzz" 675 * StringUtils.replacePattern("", ".*", "zzz") = "zzz" 676 * StringUtils.replacePattern("", ".+", "zzz") = "" 677 * StringUtils.replacePattern("<__>\n<__>", "<.*>", "z") = "z" 678 * StringUtils.replacePattern("ABCabc123", "[a-z]", "_") = "ABC___123" 679 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123" 680 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "") = "ABC123" 681 * StringUtils.replacePattern("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit" 682 * }</pre> 683 * 684 * @param text 685 * the source string 686 * @param regex 687 * the regular expression to which this string is to be matched 688 * @param replacement 689 * the string to be substituted for each match 690 * @return The resulting {@link String} 691 * @see #replaceAll(String, String, String) 692 * @see String#replaceAll(String, String) 693 * @see Pattern#DOTALL 694 * @since 3.18.0 695 */ 696 public static String replacePattern(final CharSequence text, final String regex, final String replacement) { 697 if (ObjectUtils.anyNull(text, regex, replacement)) { 698 return toStringOrNull(text); 699 } 700 return dotAllMatcher(regex, text).replaceAll(replacement); 701 } 702 703 /** 704 * Replaces each substring of the source String that matches the given regular expression with the given 705 * replacement using the {@link Pattern#DOTALL} option. DOTALL is also known as single-line mode in Perl. 706 * 707 * This call is a {@code null} safe equivalent to: 708 * <ul> 709 * <li>{@code text.replaceAll("(?s)" + regex, replacement)}</li> 710 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(text).replaceAll(replacement)}</li> 711 * </ul> 712 * 713 * <p>A {@code null} reference passed to this method is a no-op.</p> 714 * 715 * <pre>{@code 716 * StringUtils.replacePattern(null, *, *) = null 717 * StringUtils.replacePattern("any", (String) null, *) = "any" 718 * StringUtils.replacePattern("any", *, null) = "any" 719 * StringUtils.replacePattern("", "", "zzz") = "zzz" 720 * StringUtils.replacePattern("", ".*", "zzz") = "zzz" 721 * StringUtils.replacePattern("", ".+", "zzz") = "" 722 * StringUtils.replacePattern("<__>\n<__>", "<.*>", "z") = "z" 723 * StringUtils.replacePattern("ABCabc123", "[a-z]", "_") = "ABC___123" 724 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123" 725 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "") = "ABC123" 726 * StringUtils.replacePattern("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit" 727 * }</pre> 728 * 729 * @param text 730 * the source string 731 * @param regex 732 * the regular expression to which this string is to be matched 733 * @param replacement 734 * the string to be substituted for each match 735 * @return The resulting {@link String} 736 * @see #replaceAll(String, String, String) 737 * @see String#replaceAll(String, String) 738 * @see Pattern#DOTALL 739 * @deprecated Use {@link #replacePattern(CharSequence, String, String)}. 740 */ 741 @Deprecated 742 public static String replacePattern(final String text, final String regex, final String replacement) { 743 return replacePattern((CharSequence) text, regex, replacement); 744 } 745 746 private static String toStringOrNull(final CharSequence text) { 747 return Objects.toString(text, null); 748 } 749 750 /** 751 * Make private in 4.0. 752 * 753 * @deprecated TODO Make private in 4.0. 754 */ 755 @Deprecated 756 public RegExUtils() { 757 // empty 758 } 759}