diff --git a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java
index 3a6119bd1..55641340b 100755
--- a/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java
+++ b/hutool-core/src/main/java/cn/hutool/core/text/CharSequenceUtil.java
@@ -2552,7 +2552,8 @@ public class CharSequenceUtil extends StrChecker {
}
/**
- * 去掉字符包装,如果未被包装则返回原字符串
+ * 去掉字符包装,如果未被包装则返回原字符串
+ * 此方法要求prefix和suffix都存在,如果只有一个,不做去除。
*
* @param str 字符串
* @param prefix 前置字符串
diff --git a/hutool-core/src/main/java/cn/hutool/core/text/StrRegionMatcher.java b/hutool-core/src/main/java/cn/hutool/core/text/StrRegionMatcher.java
index ae9b3a4f9..8c1a85c27 100644
--- a/hutool-core/src/main/java/cn/hutool/core/text/StrRegionMatcher.java
+++ b/hutool-core/src/main/java/cn/hutool/core/text/StrRegionMatcher.java
@@ -4,7 +4,22 @@ import java.io.Serializable;
import java.util.function.BiPredicate;
/**
- * 字符串区域匹配器,用于匹配字串是头部匹配还是尾部匹配
+ * 字符串区域匹配器,用于匹配字串是头部匹配还是尾部匹配。
+ * offset用于锚定开始或结束位置,正数表示从开始偏移,负数表示从后偏移
+ *
+ * a b c d e f
+ * | | | |
+ * 0 1 c d -2 -1
+ *
+ *
+ * 例如以下匹配都为{@code true}:
+ *
+ * offset str strToCheck
+ * 0 abcdef ab
+ * 1 abcdef bc
+ * -1 abcdef ef
+ * -2 abcdef de
+ *
*
* @author looly
* @since 6.0.0
@@ -14,7 +29,10 @@ public class StrRegionMatcher implements BiPredicate
private final boolean ignoreCase;
private final boolean ignoreEquals;
- private final boolean isPrefix;
+ /**
+ * 匹配位置,正数表示从开始偏移,负数表示从后偏移
+ */
+ private final int offset;
/**
* 构造
@@ -24,9 +42,20 @@ public class StrRegionMatcher implements BiPredicate
* @param isPrefix {@code true}表示检查开头匹配,{@code false}检查末尾匹配
*/
public StrRegionMatcher(final boolean ignoreCase, final boolean ignoreEquals, final boolean isPrefix) {
+ this(ignoreCase, ignoreEquals, isPrefix ? 0 : -1);
+ }
+
+ /**
+ * 构造
+ *
+ * @param ignoreCase 是否忽略大小写
+ * @param ignoreEquals 是否忽略字符串相等的情况
+ * @param offset 匹配位置,正数表示从开始偏移,负数表示从后偏移
+ */
+ public StrRegionMatcher(final boolean ignoreCase, final boolean ignoreEquals, final int offset) {
this.ignoreCase = ignoreCase;
this.ignoreEquals = ignoreEquals;
- this.isPrefix = isPrefix;
+ this.offset = offset;
}
@Override
@@ -38,9 +67,11 @@ public class StrRegionMatcher implements BiPredicate
return null == str && null == strToCheck;
}
- final int toffset = isPrefix ? 0 : str.length() - strToCheck.length();
+ final int strToCheckLength = strToCheck.length();
+ final int toffset = this.offset >= 0 ?
+ this.offset : str.length() - strToCheckLength + this.offset + 1;
final boolean matches = str.toString()
- .regionMatches(ignoreCase, toffset, strToCheck.toString(), 0, strToCheck.length());
+ .regionMatches(ignoreCase, toffset, strToCheck.toString(), 0, strToCheckLength);
if (matches) {
return (false == ignoreEquals) || (false == StrUtil.equals(str, strToCheck, ignoreCase));
diff --git a/hutool-core/src/main/java/cn/hutool/core/text/StrTrimer.java b/hutool-core/src/main/java/cn/hutool/core/text/StrTrimer.java
index b173e3139..abe4b6db0 100644
--- a/hutool-core/src/main/java/cn/hutool/core/text/StrTrimer.java
+++ b/hutool-core/src/main/java/cn/hutool/core/text/StrTrimer.java
@@ -7,7 +7,7 @@ import java.util.function.Predicate;
import java.util.function.UnaryOperator;
/**
- * 字符串头尾去除器
+ * 字符串头尾指定字符去除器
* 按照断言,除去字符串头尾部的断言为真的字符,如果字符串是{@code null},依然返回{@code null}。
*
* @author looly
diff --git a/hutool-core/src/test/java/cn/hutool/core/text/StrRegionMatcherTest.java b/hutool-core/src/test/java/cn/hutool/core/text/StrRegionMatcherTest.java
new file mode 100644
index 000000000..bab77315d
--- /dev/null
+++ b/hutool-core/src/test/java/cn/hutool/core/text/StrRegionMatcherTest.java
@@ -0,0 +1,56 @@
+package cn.hutool.core.text;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+public class StrRegionMatcherTest {
+ @Test
+ public void matchPrefixTest() {
+ final StrRegionMatcher matcher = new StrRegionMatcher(
+ false, false, true);
+ final boolean test = matcher.test("abcdef", "ab");
+ Assert.assertTrue(test);
+ }
+
+ @Test
+ public void matchSuffixTest() {
+ final StrRegionMatcher matcher = new StrRegionMatcher(
+ false, false, false);
+ final boolean test = matcher.test("abcdef", "ef");
+ Assert.assertTrue(test);
+ }
+
+ @Test
+ public void matchOffsetTest1() {
+ final StrRegionMatcher matcher = new StrRegionMatcher(
+ false, false, 1);
+ final boolean test = matcher.test("abcdef", "bc");
+ Assert.assertTrue(test);
+ }
+
+ @Test
+ public void matchOffsetTest2() {
+ final StrRegionMatcher matcher = new StrRegionMatcher(
+ false, false, -2);
+ final boolean test = matcher.test("abcdef", "de");
+ Assert.assertTrue(test);
+ }
+
+ @Test
+ public void matchOffsetTest3() {
+ // 部分越界
+ final StrRegionMatcher matcher = new StrRegionMatcher(
+ false, false, 5);
+ final boolean test = matcher.test("abcdef", "de");
+ Assert.assertFalse(test);
+ }
+
+ @Test
+ public void matchOffsetTest4() {
+ // 完全越界
+ final StrRegionMatcher matcher = new StrRegionMatcher(
+ false, false, 6);
+ final boolean test = matcher.test("abcdef", "de");
+ Assert.assertFalse(test);
+ }
+}