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
19 import java.util.Objects;
20 import java.util.regex.Matcher;
21 import java.util.regex.Pattern;
22
23 /**
24 * Helpers to process Strings using regular expressions.
25 *
26 * @see java.util.regex.Pattern
27 * @since 3.8
28 */
29 public class RegExUtils {
30
31 /**
32 * The pattern to split version strings.
33 */
34 static final Pattern VERSION_SPLIT_PATTERN = Pattern.compile("\\.");
35
36 /**
37 * Compiles the given regular expression into a pattern with the {@link Pattern#DOTALL} flag.
38 *
39 * @param regex The expression to be compiled.
40 * @return The given regular expression compiled into a pattern with the {@link Pattern#DOTALL} flag.
41 * @since 3.13.0
42 */
43 public static Pattern dotAll(final String regex) {
44 return Pattern.compile(regex, Pattern.DOTALL);
45 }
46
47 /**
48 * 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
49 * this pattern.
50 *
51 * @param regex The expression to be compiled.
52 * @param text The character sequence to be matched.
53 * @return A new matcher for this pattern.
54 * @since 3.18.0
55 */
56 public static Matcher dotAllMatcher(final String regex, final CharSequence text) {
57 return dotAll(regex).matcher(text);
58 }
59
60 /**
61 * 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
62 * this pattern.
63 *
64 * @param regex The expression to be compiled.
65 * @param text The character sequence to be matched.
66 * @return A new matcher for this pattern.
67 * @since 3.13.0
68 * @deprecated Use {@link #dotAllMatcher(String, CharSequence)}.
69 */
70 @Deprecated
71 public static Matcher dotAllMatcher(final String regex, final String text) {
72 return dotAll(regex).matcher(text);
73 }
74
75 /**
76 * Removes each substring of the text String that matches the given regular expression pattern.
77 *
78 * This method is a {@code null} safe equivalent to:
79 * <ul>
80 * <li>{@code pattern.matcher(text).replaceAll(StringUtils.EMPTY)}</li>
81 * </ul>
82 *
83 * <p>
84 * A {@code null} reference passed to this method is a no-op.
85 * </p>
86 *
87 * <pre>{@code
88 * RegExUtils.removeAll(null, *) = null
89 * RegExUtils.removeAll("any", (Pattern) null) = "any"
90 * RegExUtils.removeAll("any", Pattern.compile("")) = "any"
91 * RegExUtils.removeAll("any", Pattern.compile(".*")) = ""
92 * RegExUtils.removeAll("any", Pattern.compile(".+")) = ""
93 * RegExUtils.removeAll("abc", Pattern.compile(".?")) = ""
94 * RegExUtils.removeAll("A<__>\n<__>B", Pattern.compile("<.*>")) = "A\nB"
95 * RegExUtils.removeAll("A<__>\n<__>B", Pattern.compile("(?s)<.*>")) = "AB"
96 * RegExUtils.removeAll("A<__>\n<__>B", Pattern.compile("<.*>", Pattern.DOTALL)) = "AB"
97 * RegExUtils.removeAll("ABCabc123abc", Pattern.compile("[a-z]")) = "ABC123"
98 * }</pre>
99 *
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 }