Repository: nifi Updated Branches: refs/heads/master c6af6be44 -> 93795bc7b
NIFI-1915 Fixed '$' escape logic. Fixed '$' escape logic (if not followed by number) to use Matcher.quoteReplacement(java.lang.String) to suppress its special meaning so it could be treated as literal. This closes #466. Signed-off-by: Pierre Villard <[email protected]> Project: http://git-wip-us.apache.org/repos/asf/nifi/repo Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/93795bc7 Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/93795bc7 Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/93795bc7 Branch: refs/heads/master Commit: 93795bc7ba411077649351b935cb15970a7c417f Parents: c6af6be Author: Oleg Zhurakousky <[email protected]> Authored: Tue May 24 09:30:51 2016 -0400 Committer: Pierre Villard <[email protected]> Committed: Wed Jun 1 20:17:59 2016 +0200 ---------------------------------------------------------------------- .../nifi/processors/standard/ReplaceText.java | 21 +++++++++++--- .../processors/standard/TestReplaceText.java | 30 ++++++++++++++++++++ 2 files changed, 47 insertions(+), 4 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/nifi/blob/93795bc7/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ReplaceText.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ReplaceText.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ReplaceText.java index 43a01c7..59e0da6 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ReplaceText.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/main/java/org/apache/nifi/processors/standard/ReplaceText.java @@ -73,6 +73,8 @@ import org.apache.nifi.util.StopWatch; + "the content that matches the Regular Expression with some alternate value.") public class ReplaceText extends AbstractProcessor { + private static Pattern REPLACEMENT_NORMALIZATION_PATTERN = Pattern.compile("(\\$\\D)"); + // Constants public static final String LINE_BY_LINE = "Line-by-Line"; public static final String ENTIRE_TEXT = "Entire text"; @@ -520,8 +522,7 @@ public class ReplaceText extends AbstractProcessor { String replacement = context.getProperty(REPLACEMENT_VALUE).evaluateAttributeExpressions(flowFile, additionalAttrs, escapeBackRefDecorator).getValue(); replacement = escapeLiteralBackReferences(replacement, numCapturingGroups); - // If we have a $ followed by anything other than a number, then escape it. E.g., $d becomes \$d so that it can be used as a literal in a regex. - final String replacementFinal = replacement.replaceAll("(\\$\\D)", "\\\\$1"); + String replacementFinal = normalizeReplacementString(replacement); final String updatedValue = contentString.replaceAll(searchRegex, replacementFinal); updatedFlowFile = session.write(flowFile, new OutputStreamCallback() { @@ -553,8 +554,7 @@ public class ReplaceText extends AbstractProcessor { String replacement = context.getProperty(REPLACEMENT_VALUE).evaluateAttributeExpressions(flowFile, additionalAttrs, escapeBackRefDecorator).getValue(); replacement = escapeLiteralBackReferences(replacement, numCapturingGroups); - // If we have a $ followed by anything other than a number, then escape it. E.g., $d becomes \$d so that it can be used as a literal in a regex. - final String replacementFinal = replacement.replaceAll("(\\$\\D)", "\\\\$1"); + String replacementFinal = normalizeReplacementString(replacement); final String updatedValue = oneLine.replaceAll(searchRegex, replacementFinal); bw.write(updatedValue); @@ -635,6 +635,19 @@ public class ReplaceText extends AbstractProcessor { } } + /** + * If we have a '$' followed by anything other than a number, then escape + * it. E.g., '$d' becomes '\$d' so that it can be used as a literal in a + * regex. + */ + private static String normalizeReplacementString(String replacement) { + String replacementFinal = replacement; + if (REPLACEMENT_NORMALIZATION_PATTERN.matcher(replacement).find()) { + replacementFinal = Matcher.quoteReplacement(replacement); + } + return replacementFinal; + } + private interface ReplacementStrategyExecutor { FlowFile replace(FlowFile flowFile, ProcessSession session, ProcessContext context, String evaluateMode, Charset charset, int maxBufferSize); http://git-wip-us.apache.org/repos/asf/nifi/blob/93795bc7/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestReplaceText.java ---------------------------------------------------------------------- diff --git a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestReplaceText.java b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestReplaceText.java index 561a1e0..a6e0971 100644 --- a/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestReplaceText.java +++ b/nifi-nar-bundles/nifi-standard-bundle/nifi-standard-processors/src/test/java/org/apache/nifi/processors/standard/TestReplaceText.java @@ -64,6 +64,36 @@ public class TestReplaceText { } @Test + public void testWithEscaped$InReplacemenmt() throws IOException { + final TestRunner runner = TestRunners.newTestRunner(new ReplaceText()); + runner.setValidateExpressionUsage(false); + runner.setProperty(ReplaceText.SEARCH_VALUE, "(?s:^.*$)"); + runner.setProperty(ReplaceText.REPLACEMENT_VALUE, "a\\$b"); + + runner.enqueue("a$a,b,c,d"); + runner.run(); + + runner.assertAllFlowFilesTransferred(ReplaceText.REL_SUCCESS, 1); + final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceText.REL_SUCCESS).get(0); + out.assertContentEquals("a\\$b".getBytes("UTF-8")); + } + + @Test + public void testWithUnEscaped$InReplacemenmt() throws IOException { + final TestRunner runner = TestRunners.newTestRunner(new ReplaceText()); + runner.setValidateExpressionUsage(false); + runner.setProperty(ReplaceText.SEARCH_VALUE, "(?s:^.*$)"); + runner.setProperty(ReplaceText.REPLACEMENT_VALUE, "a$b"); + + runner.enqueue("a$a,b,c,d"); + runner.run(); + + runner.assertAllFlowFilesTransferred(ReplaceText.REL_SUCCESS, 1); + final MockFlowFile out = runner.getFlowFilesForRelationship(ReplaceText.REL_SUCCESS).get(0); + out.assertContentEquals("a$b".getBytes("UTF-8")); + } + + @Test public void testPrependSimple() throws IOException { final TestRunner runner = TestRunners.newTestRunner(new ReplaceText()); runner.setValidateExpressionUsage(false);
