diff --git a/src/System.Management.Automation/engine/lang/parserutils.cs b/src/System.Management.Automation/engine/lang/parserutils.cs index 354c63b883..300d39a5af 100644 --- a/src/System.Management.Automation/engine/lang/parserutils.cs +++ b/src/System.Management.Automation/engine/lang/parserutils.cs @@ -895,14 +895,13 @@ namespace System.Management.Automation "BadReplaceArgument", ParserStrings.BadReplaceArgument, ignoreCase ? "-ireplace" : "-replace", rList.Count); } - if(rList.Count > 1) - { - substitute = rList[1]; - } - if (rList.Count > 0) { pattern = rList[0]; + if (rList.Count > 1) + { + substitute = rList[1]; + } } } else @@ -963,14 +962,29 @@ namespace System.Management.Automation /// The result of the regex.Replace operation private static object ReplaceOperatorImpl(ExecutionContext context, string input, Regex regex, object substitute) { - MatchEvaluator matchEvaluator = null; - if (!(substitute is string) && LanguagePrimitives.TryConvertTo(substitute, out matchEvaluator)) + switch (substitute) { - return regex.Replace(input, matchEvaluator); - } + 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()); - string replacement = PSObject.ToStringParser(context, substitute); - return regex.Replace(input, replacement); + return PSObject.ToStringParser(context, result);; + }; + return regex.Replace(input, me); + + case object val when LanguagePrimitives.TryConvertTo(val, out MatchEvaluator matchEvaluator): + return regex.Replace(input, matchEvaluator); + + default: + string replacement = PSObject.ToStringParser(context, substitute); + return regex.Replace(input, replacement); + } } /// diff --git a/test/powershell/Language/Operators/ReplaceOperator.Tests.ps1 b/test/powershell/Language/Operators/ReplaceOperator.Tests.ps1 index 2cb807d86d..be428d9dbc 100644 --- a/test/powershell/Language/Operators/ReplaceOperator.Tests.ps1 +++ b/test/powershell/Language/Operators/ReplaceOperator.Tests.ps1 @@ -1,3 +1,6 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. + Describe "Replace Operator" -Tags CI { Context "Replace operator" { It "Replace operator can replace string values using regular expressions" { @@ -40,7 +43,7 @@ Describe "Replace Operator" -Tags CI { } It "Replace operator can take a ScriptBlock in place of a substitution string" { - $res = "ID ABC123" -replace "\b[A-C]+", {return "X" * $args[0].Value.Length} + $res = "ID ABC123" -replace "\b[A-C]+", {return "X" * $_[0].Value.Length} $res | Should BeExactly "ID XXX123" }