@@ -755,22 +755,82 @@ def replace(string: Optional[str], pattern: Union[str, re.Pattern], replacement:
755
755
if isinstance (pattern , str ):
756
756
if not pattern :
757
757
raise jexception .JException ("Second argument of replace function cannot be an empty string" , 0 )
758
- if limit is None :
759
- if isinstance (pattern , str ):
760
- return re .sub (pattern , str (replacement ), string )
761
- else :
762
- return Functions .safe_replace_all (string , pattern , replacement )
763
- else :
758
+
759
+ if limit is not None and limit < 0 :
760
+ raise jexception .JException ("Fourth argument of replace function must evaluate to a positive number" , 0 )
761
+
762
+ def string_replacer (match ):
763
+ result = ''
764
+ position = 0
765
+ repl = str (replacement )
766
+ while position < len (repl ):
767
+ index = repl .find ('$' , position )
768
+ if index == - 1 :
769
+ result += repl [position :]
770
+ break
771
+ result += repl [position :index ]
772
+ position = index + 1
773
+ if position < len (repl ):
774
+ dollar_val = repl [position ]
775
+ if dollar_val == '$' :
776
+ result += '$'
777
+ position += 1
778
+ elif dollar_val == '0' :
779
+ result += match .group (0 )
780
+ position += 1
781
+ else :
782
+ max_digits = len (str (len (match .groups ())))
783
+ group_num = repl [position :position + max_digits ]
784
+ if group_num .isdigit ():
785
+ group_index = int (group_num )
786
+ if 0 < group_index <= len (match .groups ()):
787
+ result += match .group (group_index ) or ''
788
+ position += len (group_num )
789
+ else :
790
+ result += '$'
791
+ else :
792
+ result += '$'
793
+ else :
794
+ result += '$'
795
+ return result
764
796
765
- if limit < 0 :
766
- raise jexception .JException ("Fourth argument of replace function must evaluate to a positive number" , 0 )
797
+ if callable (replacement ):
798
+ replacer = lambda m : replacement (m .groupdict ())
799
+ elif isinstance (replacement , str ):
800
+ replacer = string_replacer
801
+ else :
802
+ replacer = lambda m : str (replacement )
767
803
768
- for i in range (0 , limit ):
769
- if isinstance (pattern , str ):
770
- string = re .sub (pattern , str (replacement ), string , 1 )
771
- else :
772
- string = Functions .safe_replace_first (string , pattern , str (replacement ))
773
- return string
804
+ if isinstance (pattern , str ):
805
+ # Use string methods for literal string patterns
806
+ result = ''
807
+ position = 0
808
+ count = 0
809
+ while True :
810
+ if limit is not None and count >= limit :
811
+ result += string [position :]
812
+ break
813
+ index = string .find (pattern , position )
814
+ if index == - 1 :
815
+ result += string [position :]
816
+ break
817
+ result += string [position :index ]
818
+ match = re .match (re .escape (pattern ), string [index :])
819
+ result += replacer (match )
820
+ position = index + len (pattern )
821
+ count += 1
822
+ return result
823
+ else :
824
+ # Use regex for pattern objects
825
+ if limit is None :
826
+ return Functions .safe_replace_all (string , pattern , replacement )
827
+ else :
828
+ count = 0
829
+ result = string
830
+ while count < limit :
831
+ result = Functions .safe_replace_first (result , pattern , str (replacement ))
832
+ count += 1
833
+ return result
774
834
775
835
#
776
836
# Base64 encode a string
0 commit comments