@@ -965,6 +965,7 @@ internal static object ReplaceOperator(ExecutionContext context, IScriptExtent e
965965 }
966966 }
967967
968+ var replacer = ReplaceOperatorImpl . Create ( context , rr , substitute ) ;
968969 IEnumerator list = LanguagePrimitives . GetEnumerator ( lval ) ;
969970 if ( list == null )
970971 {
@@ -978,53 +979,63 @@ internal static object ReplaceOperator(ExecutionContext context, IScriptExtent e
978979 lvalString = lval ? . ToString ( ) ?? string . Empty ;
979980 }
980981
981- return ReplaceOperatorImpl ( context , lvalString , rr , substitute ) ;
982+ return replacer . Replace ( lvalString ) ;
982983 }
983984 else
984985 {
985986 List < object > resultList = new List < object > ( ) ;
986987 while ( ParserOps . MoveNext ( context , errorPosition , list ) )
987988 {
988989 string lvalString = PSObject . ToStringParser ( context , ParserOps . Current ( errorPosition , list ) ) ;
989- resultList . Add ( ReplaceOperatorImpl ( context , lvalString , rr , substitute ) ) ;
990+ resultList . Add ( replacer . Replace ( lvalString ) ) ;
990991 }
991992
992993 return resultList . ToArray ( ) ;
993994 }
994995 }
995996
996- /// <summary>
997- /// ReplaceOperator implementation.
998- /// Abstracts away conversion of the optional substitute parameter to either a string or a MatchEvaluator delegate
999- /// and finally returns the result of the final Regex.Replace operation.
1000- /// </summary>
1001- /// <param name="context">The execution context in which to evaluate the expression.</param>
1002- /// <param name="input">The input string.</param>
1003- /// <param name="regex">A Regex instance.</param>
1004- /// <param name="substitute">The substitute value.</param>
1005- /// <returns>The result of the regex.Replace operation.</returns>
1006- private static object ReplaceOperatorImpl ( ExecutionContext context , string input , Regex regex , object substitute )
997+ private struct ReplaceOperatorImpl
1007998 {
1008- switch ( substitute )
999+ public static ReplaceOperatorImpl Create ( ExecutionContext context , Regex regex , object substitute )
1000+ {
1001+ return new ReplaceOperatorImpl ( context , regex , substitute ) ;
1002+ }
1003+
1004+ private readonly Regex _regex ;
1005+ private readonly string _cachedReplacementString ;
1006+ private readonly MatchEvaluator _cachedMatchEvaluator ;
1007+
1008+ private ReplaceOperatorImpl (
1009+ ExecutionContext context ,
1010+ Regex regex ,
1011+ object substitute )
10091012 {
1010- case string replacementString :
1011- return regex . Replace ( input , replacementString ) ;
1013+ _regex = regex ;
1014+ _cachedReplacementString = null ;
1015+ _cachedMatchEvaluator = null ;
1016+
1017+ switch ( substitute )
1018+ {
1019+ case string replacement :
1020+ _cachedReplacementString = replacement ;
1021+ break ;
10121022
1013- case ScriptBlock sb :
1014- MatchEvaluator me = GetMatchEvaluator ( context , sb ) ;
1015- return regex . Replace ( input , me ) ;
1023+ case ScriptBlock sb :
1024+ _cachedMatchEvaluator = GetMatchEvaluator ( context , sb ) ;
1025+ break ;
10161026
1017- case object val when LanguagePrimitives . TryConvertTo ( val , out MatchEvaluator matchEvaluator ) :
1018- return regex . Replace ( input , matchEvaluator ) ;
1027+ case object val when LanguagePrimitives . TryConvertTo ( val , out _cachedMatchEvaluator ) :
1028+ break ;
10191029
1020- default :
1021- string replacement = PSObject . ToStringParser ( context , substitute ) ;
1022- return regex . Replace ( input , replacement ) ;
1030+ default :
1031+ _cachedReplacementString = PSObject . ToStringParser ( context , substitute ) ;
1032+ break ;
1033+ }
10231034 }
10241035
10251036 // Local helper function to avoid creating an instance of the generated delegate helper class
10261037 // every time 'ReplaceOperatorImpl' is invoked.
1027- static MatchEvaluator GetMatchEvaluator ( ExecutionContext context , ScriptBlock sb )
1038+ private static MatchEvaluator GetMatchEvaluator ( ExecutionContext context , ScriptBlock sb )
10281039 {
10291040 return match =>
10301041 {
@@ -1039,6 +1050,22 @@ static MatchEvaluator GetMatchEvaluator(ExecutionContext context, ScriptBlock sb
10391050 return PSObject . ToStringParser ( context , result ) ;
10401051 } ;
10411052 }
1053+
1054+ /// <summary>
1055+ /// ReplaceOperator implementation.
1056+ /// Abstracts away conversion of the optional substitute parameter to either a string or a MatchEvaluator delegate
1057+ /// and finally returns the result of the final Regex.Replace operation.
1058+ /// </summary>
1059+ public object Replace ( string input )
1060+ {
1061+ if ( _cachedReplacementString is not null )
1062+ {
1063+ return _regex . Replace ( input , _cachedReplacementString ) ;
1064+ }
1065+
1066+ Dbg . Assert ( _cachedMatchEvaluator is not null , "_cachedMatchEvaluator should be not null when code reach here." ) ;
1067+ return _regex . Replace ( input , _cachedMatchEvaluator ) ;
1068+ }
10421069 }
10431070
10441071 /// <summary>
0 commit comments