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 * @see java.util.regex.Matcher#replaceAll(String)
414 * @see java.util.regex.Pattern
415 */
416 public static String replaceAll(final CharSequence text, final Pattern regex, final String replacement) {
417 if (ObjectUtils.anyNull(text, regex, replacement)) {
418 return toStringOrNull(text);
419 }
420 return regex.matcher(text).replaceAll(replacement);
421 }
422
423 /**
424 * Replaces each substring of the text String that matches the given regular expression pattern with the given replacement.
425 *
426 * This method is a {@code null} safe equivalent to:
427 * <ul>
428 * <li>{@code pattern.matcher(text).replaceAll(replacement)}</li>
429 * </ul>
430 *
431 * <p>A {@code null} reference passed to this method is a no-op.</p>
432 *
433 * <pre>{@code
434 * StringUtils.replaceAll(null, *, *) = null
435 * StringUtils.replaceAll("any", (Pattern) null, *) = "any"
436 * StringUtils.replaceAll("any", *, null) = "any"
437 * StringUtils.replaceAll("", Pattern.compile(""), "zzz") = "zzz"
438 * StringUtils.replaceAll("", Pattern.compile(".*"), "zzz") = "zzz"
439 * StringUtils.replaceAll("", Pattern.compile(".+"), "zzz") = ""
440 * StringUtils.replaceAll("abc", Pattern.compile(""), "ZZ") = "ZZaZZbZZcZZ"
441 * StringUtils.replaceAll("<__>\n<__>", Pattern.compile("<.*>"), "z") = "z\nz"
442 * StringUtils.replaceAll("<__>\n<__>", Pattern.compile("<.*>", Pattern.DOTALL), "z") = "z"
443 * StringUtils.replaceAll("<__>\n<__>", Pattern.compile("(?s)<.*>"), "z") = "z"
444 * StringUtils.replaceAll("ABCabc123", Pattern.compile("[a-z]"), "_") = "ABC___123"
445 * StringUtils.replaceAll("ABCabc123", Pattern.compile("[^A-Z0-9]+"), "_") = "ABC_123"
446 * StringUtils.replaceAll("ABCabc123", Pattern.compile("[^A-Z0-9]+"), "") = "ABC123"
447 * StringUtils.replaceAll("Lorem ipsum dolor sit", Pattern.compile("( +)([a-z]+)"), "_$2") = "Lorem_ipsum_dolor_sit"
448 * }</pre>
449 *
450 * @param text text to search and replace in, may be null.
451 * @param regex the regular expression pattern to which this string is to be matched.
452 * @param replacement the string to be substituted for each match.
453 * @return the text with any replacements processed,
454 * {@code null} if null String input.
455 * @see java.util.regex.Matcher#replaceAll(String)
456 * @see java.util.regex.Pattern
457 * @deprecated Use {@link #replaceAll(CharSequence, Pattern, String)}.
458 */
459 @Deprecated
460 public static String replaceAll(final String text, final Pattern regex, final String replacement) {
461 return replaceAll((CharSequence) text, regex, replacement);
462 }
463
464 /**
465 * Replaces each substring of the text String that matches the given regular expression
466 * with the given replacement.
467 *
468 * This method is a {@code null} safe equivalent to:
469 * <ul>
470 * <li>{@code text.replaceAll(regex, replacement)}</li>
471 * <li>{@code Pattern.compile(regex).matcher(text).replaceAll(replacement)}</li>
472 * </ul>
473 *
474 * <p>A {@code null} reference passed to this method is a no-op.</p>
475 *
476 * <p>Unlike in the {@link #replacePattern(CharSequence, String, String)} method, the {@link Pattern#DOTALL} option
477 * is NOT automatically added.
478 * To use the DOTALL option prepend {@code "(?s)"} to the regex.
479 * DOTALL is also known as single-line mode in Perl.</p>
480 *
481 * <pre>{@code
482 * StringUtils.replaceAll(null, *, *) = null
483 * StringUtils.replaceAll("any", (String) null, *) = "any"
484 * StringUtils.replaceAll("any", *, null) = "any"
485 * StringUtils.replaceAll("", "", "zzz") = "zzz"
486 * StringUtils.replaceAll("", ".*", "zzz") = "zzz"
487 * StringUtils.replaceAll("", ".+", "zzz") = ""
488 * StringUtils.replaceAll("abc", "", "ZZ") = "ZZaZZbZZcZZ"
489 * StringUtils.replaceAll("<__>\n<__>", "<.*>", "z") = "z\nz"
490 * StringUtils.replaceAll("<__>\n<__>", "(?s)<.*>", "z") = "z"
491 * StringUtils.replaceAll("ABCabc123", "[a-z]", "_") = "ABC___123"
492 * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123"
493 * StringUtils.replaceAll("ABCabc123", "[^A-Z0-9]+", "") = "ABC123"
494 * StringUtils.replaceAll("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit"
495 * }</pre>
496 *
497 * @param text text to search and replace in, may be null.
498 * @param regex the regular expression to which this string is to be matched.
499 * @param replacement the string to be substituted for each match.
500 * @return the text with any replacements processed,
501 * {@code null} if null String input.
502 * @throws java.util.regex.PatternSyntaxException
503 * if the regular expression's syntax is invalid.
504 * @see #replacePattern(String, String, String)
505 * @see String#replaceAll(String, String)
506 * @see java.util.regex.Pattern
507 * @see java.util.regex.Pattern#DOTALL
508 */
509 public static String replaceAll(final String text, final String regex, final String replacement) {
510 if (ObjectUtils.anyNull(text, regex, replacement)) {
511 return text;
512 }
513 return text.replaceAll(regex, replacement);
514 }
515
516 /**
517 * Replaces the first substring of the text string that matches the given regular expression pattern
518 * with the given replacement.
519 *
520 * This method is a {@code null} safe equivalent to:
521 * <ul>
522 * <li>{@code pattern.matcher(text).replaceFirst(replacement)}</li>
523 * </ul>
524 *
525 * <p>A {@code null} reference passed to this method is a no-op.</p>
526 *
527 * <pre>{@code
528 * StringUtils.replaceFirst(null, *, *) = null
529 * StringUtils.replaceFirst("any", (Pattern) null, *) = "any"
530 * StringUtils.replaceFirst("any", *, null) = "any"
531 * StringUtils.replaceFirst("", Pattern.compile(""), "zzz") = "zzz"
532 * StringUtils.replaceFirst("", Pattern.compile(".*"), "zzz") = "zzz"
533 * StringUtils.replaceFirst("", Pattern.compile(".+"), "zzz") = ""
534 * StringUtils.replaceFirst("abc", Pattern.compile(""), "ZZ") = "ZZabc"
535 * StringUtils.replaceFirst("<__>\n<__>", Pattern.compile("<.*>"), "z") = "z\n<__>"
536 * StringUtils.replaceFirst("<__>\n<__>", Pattern.compile("(?s)<.*>"), "z") = "z"
537 * StringUtils.replaceFirst("ABCabc123", Pattern.compile("[a-z]"), "_") = "ABC_bc123"
538 * StringUtils.replaceFirst("ABCabc123abc", Pattern.compile("[^A-Z0-9]+"), "_") = "ABC_123abc"
539 * StringUtils.replaceFirst("ABCabc123abc", Pattern.compile("[^A-Z0-9]+"), "") = "ABC123abc"
540 * StringUtils.replaceFirst("Lorem ipsum dolor sit", Pattern.compile("( +)([a-z]+)"), "_$2") = "Lorem_ipsum dolor sit"
541 * }</pre>
542 *
543 * @param text text to search and replace in, may be null.
544 * @param regex the regular expression pattern to which this string is to be matched.
545 * @param replacement the string to be substituted for the first match
546 * @return the text with the first replacement processed,
547 * {@code null} if null String input.
548 * @see java.util.regex.Matcher#replaceFirst(String)
549 * @see java.util.regex.Pattern
550 * @since 3.18.0
551 */
552 public static String replaceFirst(final CharSequence text, final Pattern regex, final String replacement) {
553 if (text == null || regex == null || replacement == null) {
554 return toStringOrNull(text);
555 }
556 return regex.matcher(text).replaceFirst(replacement);
557 }
558
559 /**
560 * Replaces the first substring of the text string that matches the given regular expression pattern
561 * with the given replacement.
562 *
563 * This method is a {@code null} safe equivalent to:
564 * <ul>
565 * <li>{@code pattern.matcher(text).replaceFirst(replacement)}</li>
566 * </ul>
567 *
568 * <p>A {@code null} reference passed to this method is a no-op.</p>
569 *
570 * <pre>{@code
571 * StringUtils.replaceFirst(null, *, *) = null
572 * StringUtils.replaceFirst("any", (Pattern) null, *) = "any"
573 * StringUtils.replaceFirst("any", *, null) = "any"
574 * StringUtils.replaceFirst("", Pattern.compile(""), "zzz") = "zzz"
575 * StringUtils.replaceFirst("", Pattern.compile(".*"), "zzz") = "zzz"
576 * StringUtils.replaceFirst("", Pattern.compile(".+"), "zzz") = ""
577 * StringUtils.replaceFirst("abc", Pattern.compile(""), "ZZ") = "ZZabc"
578 * StringUtils.replaceFirst("<__>\n<__>", Pattern.compile("<.*>"), "z") = "z\n<__>"
579 * StringUtils.replaceFirst("<__>\n<__>", Pattern.compile("(?s)<.*>"), "z") = "z"
580 * StringUtils.replaceFirst("ABCabc123", Pattern.compile("[a-z]"), "_") = "ABC_bc123"
581 * StringUtils.replaceFirst("ABCabc123abc", Pattern.compile("[^A-Z0-9]+"), "_") = "ABC_123abc"
582 * StringUtils.replaceFirst("ABCabc123abc", Pattern.compile("[^A-Z0-9]+"), "") = "ABC123abc"
583 * StringUtils.replaceFirst("Lorem ipsum dolor sit", Pattern.compile("( +)([a-z]+)"), "_$2") = "Lorem_ipsum dolor sit"
584 * }</pre>
585 *
586 * @param text text to search and replace in, may be null.
587 * @param regex the regular expression pattern to which this string is to be matched.
588 * @param replacement the string to be substituted for the first match.
589 * @return the text with the first replacement processed,
590 * {@code null} if null String input.
591 * @see java.util.regex.Matcher#replaceFirst(String)
592 * @see java.util.regex.Pattern
593 * @deprecated Use {@link #replaceFirst(CharSequence, Pattern, String)}.
594 */
595 @Deprecated
596 public static String replaceFirst(final String text, final Pattern regex, final String replacement) {
597 return replaceFirst((CharSequence) text, regex, replacement);
598 }
599
600 /**
601 * Replaces the first substring of the text string that matches the given regular expression
602 * with the given replacement.
603 *
604 * This method is a {@code null} safe equivalent to:
605 * <ul>
606 * <li>{@code text.replaceFirst(regex, replacement)}</li>
607 * <li>{@code Pattern.compile(regex).matcher(text).replaceFirst(replacement)}</li>
608 * </ul>
609 *
610 * <p>A {@code null} reference passed to this method is a no-op.</p>
611 *
612 * <p>The {@link Pattern#DOTALL} option is NOT automatically added.
613 * To use the DOTALL option prepend {@code "(?s)"} to the regex.
614 * DOTALL is also known as single-line mode in Perl.</p>
615 *
616 * <pre>{@code
617 * StringUtils.replaceFirst(null, *, *) = null
618 * StringUtils.replaceFirst("any", (String) null, *) = "any"
619 * StringUtils.replaceFirst("any", *, null) = "any"
620 * StringUtils.replaceFirst("", "", "zzz") = "zzz"
621 * StringUtils.replaceFirst("", ".*", "zzz") = "zzz"
622 * StringUtils.replaceFirst("", ".+", "zzz") = ""
623 * StringUtils.replaceFirst("abc", "", "ZZ") = "ZZabc"
624 * StringUtils.replaceFirst("<__>\n<__>", "<.*>", "z") = "z\n<__>"
625 * StringUtils.replaceFirst("<__>\n<__>", "(?s)<.*>", "z") = "z"
626 * StringUtils.replaceFirst("ABCabc123", "[a-z]", "_") = "ABC_bc123"
627 * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "_") = "ABC_123abc"
628 * StringUtils.replaceFirst("ABCabc123abc", "[^A-Z0-9]+", "") = "ABC123abc"
629 * StringUtils.replaceFirst("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum dolor sit"
630 * }</pre>
631 *
632 * @param text text to search and replace in, may be null.
633 * @param regex the regular expression to which this string is to be matched.
634 * @param replacement the string to be substituted for the first match.
635 * @return the text with the first replacement processed,
636 * {@code null} if null String input.
637 * @throws java.util.regex.PatternSyntaxException
638 * if the regular expression's syntax is invalid.
639 * @see String#replaceFirst(String, String)
640 * @see java.util.regex.Pattern
641 * @see java.util.regex.Pattern#DOTALL
642 */
643 public static String replaceFirst(final String text, final String regex, final String replacement) {
644 if (text == null || regex == null || replacement == null) {
645 return text;
646 }
647 return text.replaceFirst(regex, replacement);
648 }
649
650 /**
651 * Replaces each substring of the source String that matches the given regular expression with the given
652 * replacement using the {@link Pattern#DOTALL} option. DOTALL is also known as single-line mode in Perl.
653 *
654 * This call is a {@code null} safe equivalent to:
655 * <ul>
656 * <li>{@code text.replaceAll("(?s)" + regex, replacement)}</li>
657 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(text).replaceAll(replacement)}</li>
658 * </ul>
659 *
660 * <p>A {@code null} reference passed to this method is a no-op.</p>
661 *
662 * <pre>{@code
663 * StringUtils.replacePattern(null, *, *) = null
664 * StringUtils.replacePattern("any", (String) null, *) = "any"
665 * StringUtils.replacePattern("any", *, null) = "any"
666 * StringUtils.replacePattern("", "", "zzz") = "zzz"
667 * StringUtils.replacePattern("", ".*", "zzz") = "zzz"
668 * StringUtils.replacePattern("", ".+", "zzz") = ""
669 * StringUtils.replacePattern("<__>\n<__>", "<.*>", "z") = "z"
670 * StringUtils.replacePattern("ABCabc123", "[a-z]", "_") = "ABC___123"
671 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123"
672 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "") = "ABC123"
673 * StringUtils.replacePattern("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit"
674 * }</pre>
675 *
676 * @param text
677 * the source string.
678 * @param regex
679 * the regular expression to which this string is to be matched.
680 * @param replacement
681 * the string to be substituted for each match.
682 * @return The resulting {@link String}.
683 * @see #replaceAll(String, String, String)
684 * @see String#replaceAll(String, String)
685 * @see Pattern#DOTALL
686 * @since 3.18.0
687 */
688 public static String replacePattern(final CharSequence text, final String regex, final String replacement) {
689 if (ObjectUtils.anyNull(text, regex, replacement)) {
690 return toStringOrNull(text);
691 }
692 return dotAllMatcher(regex, text).replaceAll(replacement);
693 }
694
695 /**
696 * Replaces each substring of the source String that matches the given regular expression with the given
697 * replacement using the {@link Pattern#DOTALL} option. DOTALL is also known as single-line mode in Perl.
698 *
699 * This call is a {@code null} safe equivalent to:
700 * <ul>
701 * <li>{@code text.replaceAll("(?s)" + regex, replacement)}</li>
702 * <li>{@code Pattern.compile(regex, Pattern.DOTALL).matcher(text).replaceAll(replacement)}</li>
703 * </ul>
704 *
705 * <p>A {@code null} reference passed to this method is a no-op.</p>
706 *
707 * <pre>{@code
708 * StringUtils.replacePattern(null, *, *) = null
709 * StringUtils.replacePattern("any", (String) null, *) = "any"
710 * StringUtils.replacePattern("any", *, null) = "any"
711 * StringUtils.replacePattern("", "", "zzz") = "zzz"
712 * StringUtils.replacePattern("", ".*", "zzz") = "zzz"
713 * StringUtils.replacePattern("", ".+", "zzz") = ""
714 * StringUtils.replacePattern("<__>\n<__>", "<.*>", "z") = "z"
715 * StringUtils.replacePattern("ABCabc123", "[a-z]", "_") = "ABC___123"
716 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "_") = "ABC_123"
717 * StringUtils.replacePattern("ABCabc123", "[^A-Z0-9]+", "") = "ABC123"
718 * StringUtils.replacePattern("Lorem ipsum dolor sit", "( +)([a-z]+)", "_$2") = "Lorem_ipsum_dolor_sit"
719 * }</pre>
720 *
721 * @param text
722 * the source string.
723 * @param regex
724 * the regular expression to which this string is to be matched.
725 * @param replacement
726 * the string to be substituted for each match.
727 * @return The resulting {@link String}.
728 * @see #replaceAll(String, String, String)
729 * @see String#replaceAll(String, String)
730 * @see Pattern#DOTALL
731 * @deprecated Use {@link #replacePattern(CharSequence, String, String)}.
732 */
733 @Deprecated
734 public static String replacePattern(final String text, final String regex, final String replacement) {
735 return replacePattern((CharSequence) text, regex, replacement);
736 }
737
738 private static String toStringOrNull(final CharSequence text) {
739 return Objects.toString(text, null);
740 }
741
742 /**
743 * Make private in 4.0.
744 *
745 * @deprecated TODO Make private in 4.0.
746 */
747 @Deprecated
748 public RegExUtils() {
749 // empty
750 }
751 }