diff --git a/src/main/java/org/apache/commons/lang3/StringUtils.java b/src/main/java/org/apache/commons/lang3/StringUtils.java
index 9f2b18f5004..24b8face4a4 100644
--- a/src/main/java/org/apache/commons/lang3/StringUtils.java
+++ b/src/main/java/org/apache/commons/lang3/StringUtils.java
@@ -8778,17 +8778,59 @@ public static String substringBetween(final String str, final String tag) {
*
* @param str the String containing the substring, may be null
* @param open the String before the substring, may be null
- * @param close the String after the substring, may be null
+ * @param close the String after the substring, may be null - search first match from left to right, after the open
String found
* @return the substring, {@code null} if no match
* @since 2.0
*/
public static String substringBetween(final String str, final String open, final String close) {
+ return substringBetween(str, open, close, false);
+ }
+ /**
+ * Gets the String that is nested in between two Strings.
+ * Only the first match is returned.
+ *
+ *
A {@code null} input String returns {@code null}. + * A {@code null} open/close returns {@code null} (no match). + * An empty ("") open and close returns an empty string.
+ * + *+ * StringUtils.substringBetween("wx[b]yz", "[", "]", *) = "b" + * StringUtils.substringBetween(null, *, *, *) = null + * StringUtils.substringBetween(*, null, *, *) = null + * StringUtils.substringBetween(*, *, null, *) = null + * StringUtils.substringBetween("", "", "", *) = "" + * StringUtils.substringBetween("", "", "]", *) = null + * StringUtils.substringBetween("", "[", "]", *) = null + * StringUtils.substringBetween("yabcz", "", "", false) = "" + * StringUtils.substringBetween("yabcz", "", "", true) = "yabcz" + * StringUtils.substringBetween("yabcz", "y", "z", *) = "abc" + * StringUtils.substringBetween("yabczyabcz", "y", "z", false) = "abc" + * StringUtils.substringBetween("yabczyabcz", "y", "z", true) = "abczyabc" + * StringUtils.substringBetween("zabcyabc", "y", "z", *) = null + *+ * + * @param str the String containing the substring, may be null + * @param open the String before the substring, may be null + * @param close the String after the substring, may be null + * @param lastClose set to
true
if close String must be searched from the end of the String str
+ * @return the substring, {@code null} if no match
+ * @since 3.13
+ */
+ public static String substringBetween(final String str, final String open, final String close, final boolean lastClose) {
if (!ObjectUtils.allNotNull(str, open, close)) {
return null;
}
final int start = str.indexOf(open);
if (start != INDEX_NOT_FOUND) {
- final int end = str.indexOf(close, start + open.length());
+ int end = INDEX_NOT_FOUND;
+ if (!lastClose) {
+ end = str.indexOf(close, start + open.length());
+ } else {
+ end = str.lastIndexOf(close);
+ if (end < start + open.length()) {
+ end = INDEX_NOT_FOUND;
+ }
+ }
if (end != INDEX_NOT_FOUND) {
return str.substring(start + open.length(), end);
}
diff --git a/src/test/java/org/apache/commons/lang3/StringUtilsSubstringTest.java b/src/test/java/org/apache/commons/lang3/StringUtilsSubstringTest.java
index a6f6bf5d076..1baa283b35e 100644
--- a/src/test/java/org/apache/commons/lang3/StringUtilsSubstringTest.java
+++ b/src/test/java/org/apache/commons/lang3/StringUtilsSubstringTest.java
@@ -289,6 +289,38 @@ public void testSubstringBetween_StringStringString() {
assertEquals("abc", StringUtils.substringBetween("yabczyabcz", "y", "z"));
}
+ @Test
+ public void testSubstringBetween_StringStringStringBoolean() {
+ // same tests as testSubstringBetween_StringStringString with true parameter
+ assertNull(StringUtils.substringBetween(null, "", "", true));
+ assertNull(StringUtils.substringBetween("", null, "", true));
+ assertNull(StringUtils.substringBetween("", "", null, true));
+ assertEquals("", StringUtils.substringBetween("", "", "", true));
+
+ // not same behaviour for boolean param
+ assertEquals("", StringUtils.substringBetween("foo", "", "", false));
+ assertEquals("foo", StringUtils.substringBetween("foo", "", "", true));
+
+ assertNull(StringUtils.substringBetween("foo", "", "]", true));
+ assertNull(StringUtils.substringBetween("foo", "[", "]", true));
+
+ assertEquals(" ", StringUtils.substringBetween(" ", " ", " ", true));
+ assertEquals("bar", StringUtils.substringBetween("