There are three variations of the Replacement Operator:
-replace is implicitly case-insensitive.-ireplace is explicitly case-insensitive.-creplace is case-sensitive.The exception message returned when passing three or more comma separated values to -replace, -ireplace or -creplace is counterintuitive:
| Command | Exception Message |
| ----------------------------- |--------------------------------------------------------------------------------------|
| "foo" -replace "o", "e", "e" | InvalidOperation: The -ireplace operator allows only two elements to follow it, not 3. |
| "foo" -ireplace "o", "e", "e" | InvalidOperation: The -ireplace operator allows only two elements to follow it, not 3. |
| "foo" -creplace "o", "e", "e" | InvalidOperation: The -replace operator allows only two elements to follow it, not 3. |
As the table above demonstrates, when either the -replace or -ireplace operator is used, the message content refers to -ireplace. This is not ideal but since -replace and -ireplace are functionally equivalent it's perhaps not a big deal. But what is particularly inappropriate is that the exception message for -creplace refers to -replace.
The exception message should ideally refer to the respective operator that was used. Else at a minimum, the message returned for the -creplace operator should refer to -creplace.
The same result is exhibited in PowerShell 5.1, 7.0.0 and 7.1.0-preview.1, full version details below:
Name Value
---- -----
PSVersion 5.1.18362.628
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.18362.628
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
Name Value
---- -----
PSVersion 7.0.0
PSEdition Core
GitCommitId 7.0.0
OS Microsoft Windows 10.0.18363
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0鈥
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
Name Value
---- -----
PSVersion 7.1.0-preview.1
PSEdition Core
GitCommitId 7.1.0-preview.1
OS Microsoft Windows 10.0.18363
Platform Win32NT
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0鈥
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
WSManStackVersion 3.0
I would like to contribute to fix this issue. Please let me know!
I've looked into this a bit. It appears the parameter shown is dependent on if the replace was case sensitive, or not:
if (rList.Count > 2)
{
// only allow 1 or 2 arguments to -replace
throw InterpreterError.NewInterpreterException(rval, typeof(RuntimeException), errorPosition,
"BadReplaceArgument", ParserStrings.BadReplaceArgument, ignoreCase ? "-ireplace" : "-replace", rList.Count);
}
From the comment included, this appears to be expected:
/// <param name="ignoreCase">True for -ireplace/-replace, false for -creplace.</param>
A simple solution to restore consistency may be to rewrite the messages to including both:
if (rList.Count > 2)
{
// only allow 1 or 2 arguments to -replace
throw InterpreterError.NewInterpreterException(rval, typeof(RuntimeException), errorPosition,
"BadReplaceArgument", ParserStrings.BadReplaceArgument, ignoreCase ? "-replace/-ireplace" : "-creplace", rList.Count);
}
This would provide the following error messages:
PS> "foo" -replace "f", "j", "h"
InvalidOperation: The -ireplace/-replace operator allows only two elements to follow it, not 3.
PS> "foo" -ireplace "f", "j", "h"
InvalidOperation: The -ireplace/-replace operator allows only two elements to follow it, not 3.
PS> "foo" -creplace "f", "j", "h"
InvalidOperation: The -creplace operator allows only two elements to follow it, not 3.
Unless anyone has a clever solution to get around this limitation, I'll get a PR opened up 馃榿
I'm going to make an attempt to see if this can be improved upon
:tada:This issue was addressed in #12388, which has now been successfully released as v7.1.0-preview.3.:tada:
Handy links:
Just a thought but perhaps the problem is trying to be too specific. Instead of giving an error message referring to the actual operator (information which in the case of -replace vs -ireplace has been lost), in cases where the error cause is common to all versions of the operator (in this case, too many elements in the second operand) just using the generic operator designation would be sufficient. So in this case the error message would be
InvalidOperation: The replace operator allows only two elements to follow it, not 3.
for all three versions.
In fact, a possibly better message is
InvalidOperation: The replace operator requires exactly two elements in the second operand.
thereby removing any possible confusion about whether 1 element is acceptable (see below) and clarifying the location of the required elements instead of the somewhat nebulous "follow it". Does the replace operator allow another operator to "follow it"? Or a pipeline? Or an output redirection? How about a single element which just happens to be a two element array?
Most helpful comment
I'm going to make an attempt to see if this can be improved upon