diff --git a/hutool-core/src/main/java/org/dromara/hutool/core/text/CharSequenceUtil.java b/hutool-core/src/main/java/org/dromara/hutool/core/text/CharSequenceUtil.java index 9bf3a5fc8..718e76976 100644 --- a/hutool-core/src/main/java/org/dromara/hutool/core/text/CharSequenceUtil.java +++ b/hutool-core/src/main/java/org/dromara/hutool/core/text/CharSequenceUtil.java @@ -1331,7 +1331,7 @@ public class CharSequenceUtil extends StrValidator { final String str2 = str.toString(); int toIndex = str2.length(); - while (str2.startsWith(suffixStr, toIndex - suffixLength)){ + while (str2.startsWith(suffixStr, toIndex - suffixLength)) { toIndex -= suffixLength; } return subPre(str2, toIndex); @@ -1390,6 +1390,11 @@ public class CharSequenceUtil extends StrValidator { /** * 去除两边的指定字符串 + *
{@code
+ * "aaa_STRIPPED_bbb", "a" -> "aa_STRIPPED_bbb"
+ * "aaa_STRIPPED_bbb", "" -> "aaa_STRIPPED_bbb"
+ * }
+ *
*
* @param str 被处理的字符串
* @param prefixOrSuffix 前缀或后缀
@@ -1407,6 +1412,18 @@ public class CharSequenceUtil extends StrValidator {
/**
* 去除两边的指定字符串{@code
+ * "aaa_STRIPPED_bbb", "a", "b" -> "aa_STRIPPED_bb"
+ * "aaa_STRIPPED_bbb", null, null -> "aaa_STRIPPED_bbb"
+ * "aaa_STRIPPED_bbb", "", "" -> "aaa_STRIPPED_bbb"
+ * "aaa_STRIPPED_bbb", "", "b" -> "aaa_STRIPPED_bb"
+ * "aaa_STRIPPED_bbb", null, "b" -> "aaa_STRIPPED_bb"
+ * "aaa_STRIPPED_bbb", "a", "" -> "aa_STRIPPED_bbb"
+ * "aaa_STRIPPED_bbb", "a", null -> "aa_STRIPPED_bbb"
+ *
+ * "a", "a", "a" -> ""
+ * }
+ *
*
* @param str 被处理的字符串
* @param prefix 前缀
@@ -1419,18 +1436,116 @@ public class CharSequenceUtil extends StrValidator {
return toStringOrNull(str);
}
- int from = 0;
- int to = str.length();
-
final String str2 = str.toString();
+ int from = 0;
+ int to = str2.length();
+
if (startWith(str2, prefix)) {
from = prefix.length();
+ if(from == to){
+ // "a", "a", "a" -> ""
+ return EMPTY;
+ }
}
if (endWith(str2, suffix)) {
to -= suffix.length();
+ if(from == to){
+ // "a", "a", "a" -> ""
+ return EMPTY;
+ } else if(to < from){
+ // pre去除后和suffix有重叠,如 ("aba", "ab", "ba") -> "a"
+ to += suffix.length();
+ }
}
- return str2.substring(Math.min(from, to), Math.max(from, to));
+ return str2.substring(from, to);
+ }
+
+ /**
+ * 去除两边所有的指定字符串
+ *
+ * {@code
+ * "aaa_STRIPPED_bbb", "a" -> "_STRIPPED_bbb"
+ * "aaa_STRIPPED_bbb", "a", "b" -> "_STRIPPED_"
+ * "aaa_STRIPPED_bbb", "" -> "aaa_STRIPPED_bbb"
+ * }
+ *
+ *
+ * @param str 被处理的字符串
+ * @param prefixOrSuffix 前缀或后缀
+ * @return 处理后的字符串
+ * @since 5.8.30
+ */
+ public static String stripAll(final CharSequence str, final CharSequence prefixOrSuffix) {
+ if (equals(str, prefixOrSuffix)) {
+ return EMPTY;
+ }
+ return stripAll(str, prefixOrSuffix, prefixOrSuffix);
+ }
+
+ /**
+ * 去除两边所有的指定字符串
+ *
+ * {@code
+ * "aaa_STRIPPED_bbb", "a", "b" -> "_STRIPPED_"
+ * "aaa_STRIPPED_bbb", null, null -> "aaa_STRIPPED_bbb"
+ * "aaa_STRIPPED_bbb", "", "" -> "aaa_STRIPPED_bbb"
+ * "aaa_STRIPPED_bbb", "", "b" -> "aaa_STRIPPED_"
+ * "aaa_STRIPPED_bbb", null, "b" -> "aaa_STRIPPED_"
+ * "aaa_STRIPPED_bbb", "a", "" -> "_STRIPPED_bbb"
+ * "aaa_STRIPPED_bbb", "a", null -> "_STRIPPED_bbb"
+ *
+ * // special test
+ * "aaaaaabbb", "aaa", null -> "bbb"
+ * "aaaaaaabbb", "aa", null -> "abbb"
+ *
+ * "aaaaaaaaa", "aaa", "aa" -> ""
+ * "a", "a", "a" -> ""
+ * }
+ *
+ *
+ * @param str 被处理的字符串
+ * @param prefix 前缀
+ * @param suffix 后缀
+ * @return 处理后的字符串
+ * @since 5.8.30
+ */
+ public static String stripAll(final CharSequence str, final CharSequence prefix, final CharSequence suffix) {
+ if (isEmpty(str)) {
+ return toStringOrNull(str);
+ }
+
+ final String prefixStr = toStringOrEmpty(prefix);
+ final String suffixStr = toStringOrEmpty(suffix);
+
+ final String str2 = str.toString();
+ int from = 0;
+ int to = str2.length();
+
+ if(!prefixStr.isEmpty()){
+ while (str2.startsWith(prefixStr, from)) {
+ from += prefix.length();
+ if(from == to){
+ // "a", "a", "a" -> ""
+ return EMPTY;
+ }
+ }
+ }
+ if(!suffixStr.isEmpty()){
+ while (str2.startsWith(suffixStr, to - suffixStr.length())) {
+ to -= suffixStr.length();
+ if(from == to){
+ // "a", "a", "a" -> ""
+ return EMPTY;
+ }else if(to < from){
+ // pre去除后和suffix有重叠,如 ("aba", "ab", "ba") -> "a"
+ to += suffixStr.length();
+ break;
+ }
+ }
+ }
+
+ return str2.substring(from, to);
}
/**
diff --git a/hutool-core/src/test/java/org/dromara/hutool/core/text/CharSequenceUtilTest.java b/hutool-core/src/test/java/org/dromara/hutool/core/text/CharSequenceUtilTest.java
index 6315f774f..35e2172e3 100644
--- a/hutool-core/src/test/java/org/dromara/hutool/core/text/CharSequenceUtilTest.java
+++ b/hutool-core/src/test/java/org/dromara/hutool/core/text/CharSequenceUtilTest.java
@@ -450,4 +450,63 @@ public class CharSequenceUtilTest {
result = CharSequenceUtil.removeAllSuffix(str, prefix);
assertNull(result);
}
+
+ @Test
+ public void stripTest() {
+
+ final String SOURCE_STRING = "aaa_STRIPPED_bbb";
+
+ // ---------------------------- test strip ----------------------------
+
+ // Normal test
+ assertEquals("aa_STRIPPED_bbb", CharSequenceUtil.strip(SOURCE_STRING, "a"));
+ assertEquals(SOURCE_STRING, CharSequenceUtil.strip(SOURCE_STRING, ""));
+ assertEquals("aa_STRIPPED_bb", CharSequenceUtil.strip(SOURCE_STRING, "a", "b"));
+
+ // test null param
+ assertEquals(SOURCE_STRING, CharSequenceUtil.strip(SOURCE_STRING, null, null));
+ assertEquals(SOURCE_STRING, CharSequenceUtil.strip(SOURCE_STRING, "", ""));
+ assertEquals("aaa_STRIPPED_bb", CharSequenceUtil.strip(SOURCE_STRING, "", "b"));
+ assertEquals("aaa_STRIPPED_bb", CharSequenceUtil.strip(SOURCE_STRING, null, "b"));
+ assertEquals("aa_STRIPPED_bbb", CharSequenceUtil.strip(SOURCE_STRING, "a", ""));
+ assertEquals("aa_STRIPPED_bbb", CharSequenceUtil.strip(SOURCE_STRING, "a", null));
+ // 本次提交前无法通过的 case
+ assertEquals("", CharSequenceUtil.strip("a", "a", "a"));
+
+ // 前缀后缀有重叠,优先去掉前缀
+ assertEquals("a", CharSequenceUtil.strip("aba", "ab", "ba"));
+ }
+
+ @Test
+ void stripAllTest() {
+ final String SOURCE_STRING = "aaa_STRIPPED_bbb";
+
+ // ---------------------------- test stripAll ----------------------------
+
+ // Normal test
+ assertEquals("_STRIPPED_bbb", CharSequenceUtil.stripAll(SOURCE_STRING, "a"));
+ assertEquals(SOURCE_STRING, CharSequenceUtil.stripAll(SOURCE_STRING, ""));
+
+ // test null param
+ assertEquals("_STRIPPED_", CharSequenceUtil.stripAll(SOURCE_STRING, "a", "b"));
+ assertEquals(SOURCE_STRING, CharSequenceUtil.stripAll(SOURCE_STRING, null, null));
+ assertEquals(SOURCE_STRING, CharSequenceUtil.stripAll(SOURCE_STRING, "", ""));
+ assertEquals("aaa_STRIPPED_", CharSequenceUtil.stripAll(SOURCE_STRING, "", "b"));
+ assertEquals("aaa_STRIPPED_", CharSequenceUtil.stripAll(SOURCE_STRING, null, "b"));
+ assertEquals("_STRIPPED_bbb", CharSequenceUtil.stripAll(SOURCE_STRING, "a", ""));
+ assertEquals("_STRIPPED_bbb", CharSequenceUtil.stripAll(SOURCE_STRING, "a", null));
+
+ // special test
+ assertEquals("bbb", CharSequenceUtil.stripAll("aaaaaabbb", "aaa", null));
+ assertEquals("abbb", CharSequenceUtil.stripAll("aaaaaaabbb", "aa", null));
+
+ // aaaaaaaaa (9个a) 可以被看为 aaa_aaaa_aa
+ assertEquals("", CharSequenceUtil.stripAll("aaaaaaaaa", "aaa", "aa"));
+ // 第二次迭代后会出现 from 比 to 大的情况,原本代码是强行交换,但是回导致无法去除前后缀
+ assertEquals("", CharSequenceUtil.stripAll("a", "a", "a"));
+
+ // 前缀后缀有重叠,优先去掉前缀
+ assertEquals("a", CharSequenceUtil.stripAll("aba", "ab", "ba"));
+ assertEquals("a", CharSequenceUtil.stripAll("abababa", "ab", "ba"));
+ }
}