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>A {@code null} reference passed to this method is a no-op.</p>
84 *
85 * <pre>{@code
86 * StringUtils.removeAll(null, *) = null
87 * StringUtils.removeAll("any", (Pattern) null) = "any"
88 * StringUtils.removeAll("any", Pattern.compile("")) = "any"
89 * StringUtils.removeAll("any", Pattern.compile(".*")) = ""
90 * StringUtils.removeAll("any", Pattern.compile(".+")) = ""
91 * StringUtils.removeAll("abc", Pattern.compile(".?")) = ""
92 * StringUtils.removeAll("A<__>\n<__>B", Pattern.compile("<.*>")) = "A\nB"
93 * StringUtils.removeAll("A<__>\n<__>B", Pattern.compile("(?s)<.*>")) = "AB"
94 * StringUtils.removeAll("A<__>\n<__>B", Pattern.compile("<.*>", Pattern.DOTALL)) = "AB"
95 * StringUtils.removeAll("ABCabc123abc", Pattern.compile("[a-z]")) = "ABC123"
96 * }</pre>
97 *
98 * @param text text to remove from, may be null
99 * @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 }