diff --git a/src/main/java/org/apache/commons/text/StringSubstitutor.java b/src/main/java/org/apache/commons/text/StringSubstitutor.java index 9fce66de24..8fc9050aae 100644 --- a/src/main/java/org/apache/commons/text/StringSubstitutor.java +++ b/src/main/java/org/apache/commons/text/StringSubstitutor.java @@ -1455,13 +1455,22 @@ private Result substitute(final TextStringBuilder builder, final int offset, fin // found variable end marker if (nestedVarCount == 0) { if (escPos >= 0) { + final boolean escapedVariableStartsWithNestedPrefix = + prefixMatcher.isMatch(builder, startPos + startMatchLen, offset, bufEnd) != 0; + + final boolean hasOuterSuffix = + hasLaterSuffix(builder, pos + endMatchLen, offset, bufEnd, suffixMatcher); + + pos = escapedVariableStartsWithNestedPrefix && !hasOuterSuffix + ? escPos + : startPos + 1; + // delete escape builder.deleteCharAt(escPos); escPos = -1; lengthChange--; altered = true; bufEnd--; - pos = startPos + 1; startPos--; continue outer; } @@ -1546,6 +1555,33 @@ private Result substitute(final TextStringBuilder builder, final int offset, fin return new Result(altered, lengthChange); } + /** + * Checks whether the specified buffer contains a variable suffix after the given position. + * + * @param builder the string builder to check, not null. + * @param pos the position to start checking from. + * @param offset the start offset within the builder, must be valid. + * @param bufEnd the end offset within the builder, must be valid. + * @param suffixMatcher the suffix matcher to use, not null. + * @return true if a suffix is found after the given position. + */ + private boolean hasLaterSuffix( + final TextStringBuilder builder, + int pos, + final int offset, + final int bufEnd, + final StringMatcher suffixMatcher + ) { + while (pos < bufEnd) { + final int suffixLen = suffixMatcher.isMatch(builder, pos, offset, bufEnd); + if (suffixLen != 0) { + return true; + } + pos++; + } + return false; + } + /** * Returns a string representation of the object. * diff --git a/src/test/java/org/apache/commons/text/StringSubstitutorTest.java b/src/test/java/org/apache/commons/text/StringSubstitutorTest.java index c339189855..e913efd3d5 100644 --- a/src/test/java/org/apache/commons/text/StringSubstitutorTest.java +++ b/src/test/java/org/apache/commons/text/StringSubstitutorTest.java @@ -284,7 +284,6 @@ void testReplace_JiraText178_WeirdPatterns2() throws IOException { * Tests interpolation with weird boundary patterns. */ @Test - @Disabled void testReplace_JiraText178_WeirdPatterns3() throws IOException { doReplace("${${a}", "$${${a}", false); // not "$${1" or "${1" }