mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Add lambda support to -replace operator
Add support for replacement lambdas when using the -replace operator.
Requires minimal changes to existing code by using the following overload:
Regex.Replace(string input, MatchEvaluator evaluator)
when a ScriptBlock is passed in as the replacement argument.
This commit is contained in:
committed by
Dongbo Wang
parent
8ffc0b0e3c
commit
915639a177
@@ -881,8 +881,8 @@ namespace System.Management.Automation
|
||||
/// <returns>The result of the operator</returns>
|
||||
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;
|
||||
@@ -895,13 +895,14 @@ 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)
|
||||
{
|
||||
replacement = PSObject.ToStringParser(context, rList[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -935,8 +936,7 @@ namespace System.Management.Automation
|
||||
{
|
||||
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 +944,35 @@ namespace System.Management.Automation
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="context">The execution context in which to evaluate the expression</param>
|
||||
/// <param name="input">The input string</param>
|
||||
/// <param name="regex">A Regex instance.</param>
|
||||
/// <param name="substitute">The substitute value</param>
|
||||
/// <returns>The result of the regex.Replace operation</returns>
|
||||
private static object ReplaceOperatorImpl(ExecutionContext context, string input, Regex regex, object substitute)
|
||||
{
|
||||
MatchEvaluator matchEvaluator = null;
|
||||
if (!(substitute is string) && LanguagePrimitives.TryConvertTo(substitute, out matchEvaluator))
|
||||
{
|
||||
return regex.Replace(input, matchEvaluator);
|
||||
}
|
||||
|
||||
string replacement = PSObject.ToStringParser(context, substitute);
|
||||
return regex.Replace(input, replacement);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of the PowerShell type operators...
|
||||
/// </summary>
|
||||
@@ -1906,4 +1927,3 @@ namespace System.Management.Automation
|
||||
}
|
||||
#endregion ScriptTrace
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,64 @@
|
||||
Describe "Replace Operator" -Tags CI {
|
||||
Context "Replace operator" {
|
||||
It "Replace operator can replace string values using regular expressions" {
|
||||
$res = "Get-Process" -replace "Get", "Stop"
|
||||
$res | Should BeExactly "Stop-Process"
|
||||
|
||||
$res = "image.gif" -replace "\.gif$",".jpg"
|
||||
$res | Should BeExactly "image.jpg"
|
||||
}
|
||||
|
||||
It "Replace operator can be case-insensitive and case-sensitive" {
|
||||
$res = "book" -replace "B","C"
|
||||
$res | Should BeExactly "Cook"
|
||||
|
||||
$res = "book" -ireplace "B","C"
|
||||
$res | Should BeExactly "Cook"
|
||||
|
||||
$res = "book" -creplace "B","C"
|
||||
$res | Should BeExactly "book"
|
||||
}
|
||||
|
||||
It "Replace operator can take 2 arguments, a mandatory pattern, and an optional substitution" {
|
||||
$res = "PowerPoint" -replace "Point","Shell"
|
||||
$res | Should BeExactly "PowerShell"
|
||||
|
||||
$res = "PowerPoint" -replace "Point"
|
||||
$res | Should BeExactly "Power"
|
||||
}
|
||||
}
|
||||
|
||||
Context "Replace operator substitutions" {
|
||||
It "Replace operator supports numbered substitution groups using ```$n" {
|
||||
$res = "domain.example" -replace ".*\.(\w+)$","Tld of '`$0' is - '`$1'"
|
||||
$res | Should BeExactly "Tld of 'domain.example' is - 'example'"
|
||||
}
|
||||
|
||||
It "Replace operator supports named substitution groups using ```${name}" {
|
||||
$res = "domain.example" -replace ".*\.(?<tld>\w+)$","`${tld}"
|
||||
$res | Should BeExactly "example"
|
||||
}
|
||||
|
||||
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 | Should BeExactly "ID XXX123"
|
||||
}
|
||||
|
||||
It "Replace operator can take a MatchEvaluator in place of a substitution string" {
|
||||
$matchEvaluator = {return "X" * $args[0].Value.Length} -as [System.Text.RegularExpressions.MatchEvaluator]
|
||||
$res = "ID ABC123" -replace "\b[A-C]+", $matchEvaluator
|
||||
$res | Should BeExactly "ID XXX123"
|
||||
}
|
||||
|
||||
It "Replace operator can take a static PSMethod in place of a substitution string" {
|
||||
class R {
|
||||
static [string] Replace([System.Text.RegularExpressions.Match]$Match) {
|
||||
return "X" * $Match.Value.Length
|
||||
}
|
||||
}
|
||||
$substitutionMethod = [R]::Replace
|
||||
$res = "ID 0000123" -replace "\b0+", $substitutionMethod
|
||||
$res | Should BeExactly "ID XXXX123"
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user