我编写了这段代码,以显示格式化字符串方法的不同之处:
$arr = 'that,way'
$arr = $arr -split ","
$arr.GetType()
$arr.Count
try {
$rundmc = [string]::format("It's like {0} and that's the {1} it is",$arr)
}
catch {
Write-Host "String::format failed"
$rundmc = "It's like {0} and that's the {1} it is" -f $arr
}
Write-Host $rundmc
$arr2 = @('that','way')
$arr2.GetType()
$arr2.Count
try {
$rundmc = [string]::format("It's like {0} and that's the {1} it is",$arr2)
}
catch {
Write-Host "String::format failed"
$rundmc = "It's like {0} and that's the {1} it is" -f $arr2
}
Write-Host $rundmc
在上半部分,try
块失败并移动到可用的第二个版本的命令。
PowerShell中[string]::Format
和-f
运算符之间有什么区别?
该命令的第一个版本失败:
$rundmc = [string]::format("It's like {0} and that's the {1} it is",$arr)
Exception calling "Format" with "2" argument(s): "Index (zero based) must be greater than or equal to zero and less than the size of the argument list."
At line:1 char:1
+ $rundmc = [string]::format("It's like {0} and that's the {1} it is",$ ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : FormatException
但-f
有效。对我来说,他们看起来都相当。
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True String[] System.Array
计数
2
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
计数
2
答案 0 :(得分:3)
如果你看一下[string]::Format
的重载:
OverloadDefinitions ------------------- static string Format(string format, System.Object arg0) static string Format(string format, System.Object arg0, System.Object arg1) static string Format(string format, System.Object arg0, System.Object arg1, System.Object arg2) static string Format(string format, Params System.Object[] args) static string Format(System.IFormatProvider provider, string format, System.Object arg0) static string Format(System.IFormatProvider provider, string format, System.Object arg0, System.Object arg1) static string Format(System.IFormatProvider provider, string format, System.Object arg0, System.Object arg1, System.Object arg2) static string Format(System.IFormatProvider provider, string format, Params System.Object[] args)
您可以看到您尝试使用的是这一个:
static string Format(string format, Params System.Object[] args)
请注意,它期望其值为对象数组。
当您使用-split
运算符时,如您所见,结果为[String[]]
,而不是[Object[]]
。
$arr = 'that,way'
$arr = $arr -split ","
$arr.GetType()
$arr -is [Object[]] # false
为什么它不会被强制转换为[Object[]]
,即使它可能是?
由于这种过载:
static string Format(string format, System.Object arg0)
$arr -isnot [Object[]]
但是$arr -is [Object]
,所以此重载完全匹配。
不幸的是,由于您的格式字符串包含2个替换项,并且您调用了仅提供1的重载,因此会出现此错误。
如果您已完成[String]::Format('Just 1: {0}', $arr)
,则您的调用将成功(但结果将为Just 1: System.String[]
,因为在参数上调用了.ToString()
方法。
由于PowerShell中的大多数数组最终都为[Object[]]
,因此在定义文字数组时,或者如果您的数组被指定为管道的输出时,它可以正常工作。
例如,如果您执行以下任何操作,仍可以使用[String[]]
版本的$arr
:
[String]::Format('{0}~{1}', $($arr))
[String]::Format('{0}~{1}', ([Object[]]$arr))
[String]::Format('{0}~{1}', ($arr -as [Object[]]))
[String]::Format('{0}~{1}', ($arr|%{$_}))
-f
运算符怎么样?Let's look at the source code for it
它首先要做的是尝试将其参数转换为object[]
:
object[] formatArgsArray = formatArgs as object[];