diff --git a/src/System.Management.Automation/engine/lang/parserutils.cs b/src/System.Management.Automation/engine/lang/parserutils.cs
index 3be7adb86bf..300d39a5afc 100644
--- a/src/System.Management.Automation/engine/lang/parserutils.cs
+++ b/src/System.Management.Automation/engine/lang/parserutils.cs
@@ -881,8 +881,8 @@ private static object AsChar(object obj)
/// The result of the operator
internal static object ReplaceOperator(ExecutionContext context, IScriptExtent errorPosition, object lval, object rval, bool ignoreCase)
{
- string replacement = "";
object pattern = "";
+ object substitute = "";
rval = PSObject.Base(rval);
IList rList = rval as IList;
@@ -900,7 +900,7 @@ internal static object ReplaceOperator(ExecutionContext context, IScriptExtent e
pattern = rList[0];
if (rList.Count > 1)
{
- replacement = PSObject.ToStringParser(context, rList[1]);
+ substitute = rList[1];
}
}
}
@@ -935,8 +935,7 @@ internal static object ReplaceOperator(ExecutionContext context, IScriptExtent e
{
string lvalString = lval?.ToString() ?? String.Empty;
- // Find a single match in the string.
- return rr.Replace(lvalString, replacement);
+ return ReplaceOperatorImpl(context, lvalString, rr, substitute);
}
else
{
@@ -944,14 +943,50 @@ internal static object ReplaceOperator(ExecutionContext context, IScriptExtent e
while (ParserOps.MoveNext(context, errorPosition, list))
{
string lvalString = PSObject.ToStringParser(context, ParserOps.Current(errorPosition, list));
-
- resultList.Add(rr.Replace(lvalString, replacement));
+ resultList.Add(ReplaceOperatorImpl(context, lvalString, rr, substitute));
}
return resultList.ToArray();
}
}
+ ///
+ /// ReplaceOperator implementation.
+ /// Abstracts away conversion of the optional substitute parameter to either a string or a MatchEvaluator delegate
+ /// and finally returns the result of the final Regex.Replace operation.
+ ///
+ /// The execution context in which to evaluate the expression
+ /// The input string
+ /// A Regex instance.
+ /// The substitute value
+ /// The result of the regex.Replace operation
+ private static object ReplaceOperatorImpl(ExecutionContext context, string input, Regex regex, object substitute)
+ {
+ switch (substitute)
+ {
+ case ScriptBlock sb:
+ MatchEvaluator me = match => {
+ var result = sb.DoInvokeReturnAsIs(
+ useLocalScope: false, /* Use current scope to be consistent with 'ForEach/Where-Object {}' and 'collection.ForEach{}/Where{}' */
+ errorHandlingBehavior: ScriptBlock.ErrorHandlingBehavior.WriteToCurrentErrorPipe,
+ dollarUnder: match,
+ input: AutomationNull.Value,
+ scriptThis: AutomationNull.Value,
+ args: Utils.EmptyArray