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