This is an automated email from the ASF dual-hosted git repository.

hansva pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hop.git


The following commit(s) were added to refs/heads/master by this push:
     new 7e2f28d932 Replace in string does not handle \ as expected #2066
     new 993655b3df Merge pull request #2114 from nadment/2066
7e2f28d932 is described below

commit 7e2f28d9325600929946b4fb42c1f659d7d39b86
Author: Nicolas Adment <[email protected]>
AuthorDate: Thu Dec 29 22:30:17 2022 +0100

    Replace in string does not handle \ as expected #2066
---
 .../0026-replace-in-string-with-backslash.hpl      | 169 +++++++++++++++++++++
 .../golden-replace-in-string-with-backslash.csv    |   3 +
 .../transforms/main-0026-replace-in-string.hwf     |  13 +-
 .../golden-replace-in-string-with-backslash.json   |  32 ++++
 ...0026-replace-in-string-with-backslash UNIT.json |  38 +++++
 .../transforms/replacestring/ReplaceString.java    |  11 +-
 6 files changed, 259 insertions(+), 7 deletions(-)

diff --git 
a/integration-tests/transforms/0026-replace-in-string-with-backslash.hpl 
b/integration-tests/transforms/0026-replace-in-string-with-backslash.hpl
new file mode 100644
index 0000000000..33b863bba0
--- /dev/null
+++ b/integration-tests/transforms/0026-replace-in-string-with-backslash.hpl
@@ -0,0 +1,169 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+
+Licensed to the Apache Software Foundation (ASF) under one or more
+contributor license agreements.  See the NOTICE file distributed with
+this work for additional information regarding copyright ownership.
+The ASF licenses this file to You under the Apache License, Version 2.0
+(the "License"); you may not use this file except in compliance with
+the License.  You may obtain a copy of the License at
+
+      http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+
+-->
+<pipeline>
+  <info>
+    <name>0026-replace-in-string-with-backslash</name>
+    <name_sync_with_filename>Y</name_sync_with_filename>
+    <description/>
+    <extended_description/>
+    <pipeline_version/>
+    <pipeline_type>Normal</pipeline_type>
+    <pipeline_status>0</pipeline_status>
+    <parameters>
+      <parameter>
+        <name>REPLACE_PARAM</name>
+        <default_value>xx\zz</default_value>
+        <description>Variable with backslash</description>
+      </parameter>
+    </parameters>
+    <capture_transform_performance>N</capture_transform_performance>
+    
<transform_performance_capturing_delay>1000</transform_performance_capturing_delay>
+    
<transform_performance_capturing_size_limit>100</transform_performance_capturing_size_limit>
+    <created_user>-</created_user>
+    <created_date>2022/11/27 16:28:58.618</created_date>
+    <modified_user>-</modified_user>
+    <modified_date>2022/11/27 16:28:58.618</modified_date>
+  </info>
+  <notepads>
+  </notepads>
+  <order>
+    <hop>
+      <from>sample data</from>
+      <to>Replace in string</to>
+      <enabled>Y</enabled>
+    </hop>
+    <hop>
+      <from>Replace in string</from>
+      <to>Verify</to>
+      <enabled>Y</enabled>
+    </hop>
+  </order>
+  <transform>
+    <name>Replace in string</name>
+    <type>ReplaceString</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <fields>
+      <field>
+        <case_sensitive>N</case_sensitive>
+        <in_stream_name>value_variable</in_stream_name>
+        <is_unicode>N</is_unicode>
+        <replace_by_string>${REPLACE_PARAM}</replace_by_string>
+        <replace_string>backslash</replace_string>
+        <set_empty_string>N</set_empty_string>
+        <use_regex>N</use_regex>
+        <whole_word>N</whole_word>
+      </field>
+      <field>
+        <case_sensitive>N</case_sensitive>
+        <in_stream_name>value_field</in_stream_name>
+        <is_unicode>N</is_unicode>
+        <replace_field_by_string>replaceBy</replace_field_by_string>
+        <replace_string>backslash</replace_string>
+        <set_empty_string>N</set_empty_string>
+        <use_regex>N</use_regex>
+        <whole_word>N</whole_word>
+      </field>
+    </fields>
+    <attributes/>
+    <GUI>
+      <xloc>288</xloc>
+      <yloc>96</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>Verify</name>
+    <type>Dummy</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <attributes/>
+    <GUI>
+      <xloc>464</xloc>
+      <yloc>96</yloc>
+    </GUI>
+  </transform>
+  <transform>
+    <name>sample data</name>
+    <type>DataGrid</type>
+    <description/>
+    <distribute>Y</distribute>
+    <custom_distribution/>
+    <copies>1</copies>
+    <partitioning>
+      <method>none</method>
+      <schema_name/>
+    </partitioning>
+    <data>
+      <line>
+        <item>try to specify the backslash</item>
+        <item>try to specify the backslash</item>
+        <item>single \ backslash</item>
+      </line>
+      <line>
+        <item>method to replace the backslash</item>
+        <item>method to replace the backslash</item>
+        <item>double \\ backslash</item>
+      </line>
+    </data>
+    <fields>
+      <field>
+        <length>-1</length>
+        <precision>-1</precision>
+        <set_empty_string>N</set_empty_string>
+        <name>value_variable</name>
+        <type>String</type>
+      </field>
+      <field>
+        <length>-1</length>
+        <precision>-1</precision>
+        <set_empty_string>N</set_empty_string>
+        <name>value_field</name>
+        <type>String</type>
+      </field>
+      <field>
+        <length>-1</length>
+        <precision>-1</precision>
+        <set_empty_string>N</set_empty_string>
+        <name>replaceBy</name>
+        <type>String</type>
+      </field>
+    </fields>
+    <attributes/>
+    <GUI>
+      <xloc>128</xloc>
+      <yloc>96</yloc>
+    </GUI>
+  </transform>
+  <transform_error_handling>
+  </transform_error_handling>
+  <attributes/>
+</pipeline>
diff --git 
a/integration-tests/transforms/datasets/golden-replace-in-string-with-backslash.csv
 
b/integration-tests/transforms/datasets/golden-replace-in-string-with-backslash.csv
new file mode 100644
index 0000000000..7572c681f1
--- /dev/null
+++ 
b/integration-tests/transforms/datasets/golden-replace-in-string-with-backslash.csv
@@ -0,0 +1,3 @@
+value_variable,value_field,replaceBy
+try to specify the xx\zz,try to specify the single \ backslash,single \ 
backslash
+method to replace the xx\zz,method to replace the double \\ backslash,double 
\\ backslash
diff --git a/integration-tests/transforms/main-0026-replace-in-string.hwf 
b/integration-tests/transforms/main-0026-replace-in-string.hwf
index c6a64bb40b..04a293a334 100644
--- a/integration-tests/transforms/main-0026-replace-in-string.hwf
+++ b/integration-tests/transforms/main-0026-replace-in-string.hwf
@@ -35,14 +35,14 @@ limitations under the License.
       <description/>
       <type>SPECIAL</type>
       <attributes/>
-      <repeat>N</repeat>
-      <schedulerType>0</schedulerType>
-      <intervalSeconds>0</intervalSeconds>
-      <intervalMinutes>60</intervalMinutes>
+      <DayOfMonth>1</DayOfMonth>
       <hour>12</hour>
+      <intervalMinutes>60</intervalMinutes>
+      <intervalSeconds>0</intervalSeconds>
       <minutes>0</minutes>
+      <repeat>N</repeat>
+      <schedulerType>0</schedulerType>
       <weekDay>1</weekDay>
-      <DayOfMonth>1</DayOfMonth>
       <parallel>N</parallel>
       <xloc>128</xloc>
       <yloc>80</yloc>
@@ -57,6 +57,9 @@ limitations under the License.
         <test_name>
           <name>0026-replace-in-string UNIT</name>
         </test_name>
+        <test_name>
+          <name>0026-replace-in-string-with-backslash UNIT</name>
+        </test_name>
       </test_names>
       <parallel>N</parallel>
       <xloc>336</xloc>
diff --git 
a/integration-tests/transforms/metadata/dataset/golden-replace-in-string-with-backslash.json
 
b/integration-tests/transforms/metadata/dataset/golden-replace-in-string-with-backslash.json
new file mode 100644
index 0000000000..2e31fd46e0
--- /dev/null
+++ 
b/integration-tests/transforms/metadata/dataset/golden-replace-in-string-with-backslash.json
@@ -0,0 +1,32 @@
+{
+  "base_filename": "golden-replace-in-string-with-backslash.csv",
+  "name": "golden-replace-in-string-with-backslash",
+  "description": "",
+  "dataset_fields": [
+    {
+      "field_comment": "",
+      "field_length": -1,
+      "field_type": 2,
+      "field_precision": -1,
+      "field_name": "value_variable",
+      "field_format": ""
+    },
+    {
+      "field_comment": "",
+      "field_length": -1,
+      "field_type": 2,
+      "field_precision": -1,
+      "field_name": "value_field",
+      "field_format": ""
+    },
+    {
+      "field_comment": "",
+      "field_length": -1,
+      "field_type": 2,
+      "field_precision": -1,
+      "field_name": "replaceBy",
+      "field_format": ""
+    }
+  ],
+  "folder_name": ""
+}
\ No newline at end of file
diff --git 
a/integration-tests/transforms/metadata/unit-test/0026-replace-in-string-with-backslash
 UNIT.json 
b/integration-tests/transforms/metadata/unit-test/0026-replace-in-string-with-backslash
 UNIT.json
new file mode 100644
index 0000000000..b76747f33c
--- /dev/null
+++ 
b/integration-tests/transforms/metadata/unit-test/0026-replace-in-string-with-backslash
 UNIT.json   
@@ -0,0 +1,38 @@
+{
+  "variableValues": [],
+  "database_replacements": [],
+  "autoOpening": true,
+  "basePath": "",
+  "golden_data_sets": [
+    {
+      "field_mappings": [
+        {
+          "transform_field": "value_variable",
+          "data_set_field": "value_variable"
+        },
+        {
+          "transform_field": "value_field",
+          "data_set_field": "value_field"
+        },
+        {
+          "transform_field": "replaceBy",
+          "data_set_field": "replaceBy"
+        }
+      ],
+      "field_order": [
+        "value_variable",
+        "value_field",
+        "replaceBy"
+      ],
+      "data_set_name": "golden-replace-in-string-with-backslash",
+      "transform_name": "Verify"
+    }
+  ],
+  "input_data_sets": [],
+  "name": "0026-replace-in-string-with-backslash UNIT",
+  "description": "",
+  "persist_filename": "",
+  "trans_test_tweaks": [],
+  "pipeline_filename": "./0026-replace-in-string-with-backslash.hpl",
+  "test_type": "UNIT_TEST"
+}
\ No newline at end of file
diff --git 
a/plugins/transforms/replacestring/src/main/java/org/apache/hop/pipeline/transforms/replacestring/ReplaceString.java
 
b/plugins/transforms/replacestring/src/main/java/org/apache/hop/pipeline/transforms/replacestring/ReplaceString.java
index ae66cb14ee..4b198b0b29 100644
--- 
a/plugins/transforms/replacestring/src/main/java/org/apache/hop/pipeline/transforms/replacestring/ReplaceString.java
+++ 
b/plugins/transforms/replacestring/src/main/java/org/apache/hop/pipeline/transforms/replacestring/ReplaceString.java
@@ -115,7 +115,13 @@ public class ReplaceString extends 
BaseTransform<ReplaceStringMeta, ReplaceStrin
       return data.replaceByString[index];
     }
 
-    return getInputRowMeta().getString(row, data.replaceFieldIndex[index]);
+    String str = getInputRowMeta().getString(row, 
data.replaceFieldIndex[index]);
+    
+    // Escape the regex pattern backslash  
+    if ( str!=null ) {
+      str = str.replace("\\","\\\\");      
+    }
+    return str;
   }
 
   synchronized Object[] handleOneRow(IRowMeta rowMeta, Object[] row) throws 
HopException {
@@ -209,7 +215,8 @@ public class ReplaceString extends 
BaseTransform<ReplaceStringMeta, ReplaceStrin
           }
         } else {
           data.replaceFieldIndex[i] = -1;
-          data.replaceByString[i] = 
Const.NVL(resolve(field.getReplaceByString()), "");
+          // Escape the regex pattern backslash  
+          data.replaceByString[i] = 
Const.NVL(resolve(field.getReplaceByString()), "").replace("\\","\\\\");
         }
         data.setEmptyString[i] = field.isSettingEmptyString();
       }

Reply via email to