字符串连接在使用 Class 的成员时添加 space 而在使用变量时不添加
String concatenation adds space when using a member of a Class that is not added when using a variable instead
我从 Microsoft 找到了一些使用字符串连接的 PowerShell 代码,例如 $variable".Name"。我将此代码改编为在 class 的方法中使用,并发现了一个奇怪的行为,如这段代码所示。
Class A
{
[string]$a = "A"
[void]Test()
{
$b = $this.a
Write-Host $b"B"
Write-Host $this.a"B"
}
}
$c = [A]::new()
$c.Test()
第一个表达式 returns A 和 B 之间没有 space 的字符串,第二个表达式在它们之间有一个 space。
AB
A B
我使用“$($this.a)B”解决了这个问题,但我很想知道造成这种差异的原因。
经过一些研究,我认为这是 PowerShell 如何解析 $a"bbb"
与 $b.a"bbb"
和 ValueFromRemainingArguments
属性的组合 属性 在 Write-Host
的 -Output
参数上
基本上:
write-host $a"bbb"
等价于 write-host "$($a)bbb"
输出为 aaabbb
.
write-host $b.a"bbb"
等价于 write-host @( $b.a, "bbb" )
输出为 aaa bbb
.
长版
如果您检查为以下脚本块创建的 Ast,您可以看到 PowerShell 如何解析表达式的差异:
示例 1
$s1 = {
$a = "aaa";
write-host $a"bbb";
}
$s1.Ast.EndBlock.Statements[1].PipelineElements[0].CommandElements
给出此输出:
StringConstantType : BareWord
Value : write-host
StaticType : System.String
Extent : write-host
Parent : write-host $a"bbb"
Value : $abbb
StringConstantType : BareWord
NestedExpressions : {$a}
StaticType : System.String
Extent : $a"bbb"
Parent : write-host $a"bbb"
这会将 write-host $a"bbb"
视为等同于 write-host "$($a)bbb"
(请参阅 NestedExpressions
),如果您调用它,最终会将 aaabbb
写入控制台。
示例 2
$s2 = {
$b = [pscustomobject] @{ "a" = "aaa" };
write-host $b.a"bbb";
}
$s2.Ast.EndBlock.Statements[1].PipelineElements[0].CommandElements
给出输出:
StringConstantType : BareWord
Value : write-host
StaticType : System.String
Extent : write-host
Parent : write-host $b.a"bbb"
Expression : $b
Member : a
Static : False
NullConditional : False
StaticType : System.Object
Extent : $b.a
Parent : write-host $b.a"bbb"
StringConstantType : DoubleQuoted
Value : bbb
StaticType : System.String
Extent : "bbb"
Parent : write-host $b.a"bbb"
表示write-host $b.a"bbb"
等价于write-host $b.a "bbb"
,输出aaa bbb
但是,我们还没有完全完成...
Get-Help Write-Host
如果你调用 Get-Help Write-Host
你会看到这样的输出:
Write-Host [[-Object] <Object>] ...
但如果我们在自定义函数中镜像该签名:
function x
{
param
(
[Object] $Object
)
write-host $Object.GetType().FullName
write-host $Object
}
"Example 1"
x $a"bbb"
"Example 2"
x $b.a"bbb"
我们得到这个输出:
Example 1
System.String
aaabbb
Example 2
System.String
aaa
在第二个示例中,"bbb"
在函数调用中被丢弃,因为没有要绑定的第二个值的参数,因此 Write-Host
一定有其他事情发生嗯...
Get-Help Write-Host-满
如果我们调用 Get-Help Write-Host -Full
,我们将看到有关 cmdlet 参数的一些附加信息,它向我们展示了 -Output
参数用 FromRemainingArguments
属性:
-Object <Object>
Required? false
Position? 0
Accept pipeline input? true (ByValue, FromRemainingArguments)
Parameter set name (All)
Aliases Msg, Message
Dynamic? false
Accept wildcard characters? false
因此,如果我们将其复制到我们自己的函数中,我们将得到:
function x
{
param
(
[Parameter(ValueFromRemainingArguments=$true)]
[Object] $Object
)
write-host $Object.GetType().FullName
write-host $Object.Count
write-host ($Object | fl * | out-string)
write-host $Object
}
现在任何未绑定的参数都捆绑到我们的 $Object
:
"Example 1"
x $aaa"bbb"
"Example 2"
x $a.b"bbb"
给出:
Example 1
System.Collections.Generic.List`1[[System.Object, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]
1
aaabbb
aaabbb
System.Collections.Generic.List`1[[System.Object, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]
2
aaa
bbb
aaa bbb
我们可以看到第一个示例传递了一个包含单个字符串的通用列表,write-host
简单地逐字回显,而第二个示例将任何未绑定的值捆绑到 -Output
中,它给出了一个列表其中有两个值,PowerShell 中可枚举类型的默认序列化将项目与 space 作为分隔符。
我从 Microsoft 找到了一些使用字符串连接的 PowerShell 代码,例如 $variable".Name"。我将此代码改编为在 class 的方法中使用,并发现了一个奇怪的行为,如这段代码所示。
Class A
{
[string]$a = "A"
[void]Test()
{
$b = $this.a
Write-Host $b"B"
Write-Host $this.a"B"
}
}
$c = [A]::new()
$c.Test()
第一个表达式 returns A 和 B 之间没有 space 的字符串,第二个表达式在它们之间有一个 space。
AB
A B
我使用“$($this.a)B”解决了这个问题,但我很想知道造成这种差异的原因。
经过一些研究,我认为这是 PowerShell 如何解析 $a"bbb"
与 $b.a"bbb"
和 ValueFromRemainingArguments
属性的组合 属性 在 Write-Host
-Output
参数上
基本上:
write-host $a"bbb"
等价于write-host "$($a)bbb"
输出为aaabbb
.write-host $b.a"bbb"
等价于write-host @( $b.a, "bbb" )
输出为aaa bbb
.
长版
如果您检查为以下脚本块创建的 Ast,您可以看到 PowerShell 如何解析表达式的差异:
示例 1
$s1 = {
$a = "aaa";
write-host $a"bbb";
}
$s1.Ast.EndBlock.Statements[1].PipelineElements[0].CommandElements
给出此输出:
StringConstantType : BareWord
Value : write-host
StaticType : System.String
Extent : write-host
Parent : write-host $a"bbb"
Value : $abbb
StringConstantType : BareWord
NestedExpressions : {$a}
StaticType : System.String
Extent : $a"bbb"
Parent : write-host $a"bbb"
这会将 write-host $a"bbb"
视为等同于 write-host "$($a)bbb"
(请参阅 NestedExpressions
),如果您调用它,最终会将 aaabbb
写入控制台。
示例 2
$s2 = {
$b = [pscustomobject] @{ "a" = "aaa" };
write-host $b.a"bbb";
}
$s2.Ast.EndBlock.Statements[1].PipelineElements[0].CommandElements
给出输出:
StringConstantType : BareWord
Value : write-host
StaticType : System.String
Extent : write-host
Parent : write-host $b.a"bbb"
Expression : $b
Member : a
Static : False
NullConditional : False
StaticType : System.Object
Extent : $b.a
Parent : write-host $b.a"bbb"
StringConstantType : DoubleQuoted
Value : bbb
StaticType : System.String
Extent : "bbb"
Parent : write-host $b.a"bbb"
表示write-host $b.a"bbb"
等价于write-host $b.a "bbb"
,输出aaa bbb
但是,我们还没有完全完成...
Get-Help Write-Host
如果你调用 Get-Help Write-Host
你会看到这样的输出:
Write-Host [[-Object] <Object>] ...
但如果我们在自定义函数中镜像该签名:
function x
{
param
(
[Object] $Object
)
write-host $Object.GetType().FullName
write-host $Object
}
"Example 1"
x $a"bbb"
"Example 2"
x $b.a"bbb"
我们得到这个输出:
Example 1
System.String
aaabbb
Example 2
System.String
aaa
在第二个示例中,"bbb"
在函数调用中被丢弃,因为没有要绑定的第二个值的参数,因此 Write-Host
一定有其他事情发生嗯...
Get-Help Write-Host-满
如果我们调用 Get-Help Write-Host -Full
,我们将看到有关 cmdlet 参数的一些附加信息,它向我们展示了 -Output
参数用 FromRemainingArguments
属性:
-Object <Object>
Required? false
Position? 0
Accept pipeline input? true (ByValue, FromRemainingArguments)
Parameter set name (All)
Aliases Msg, Message
Dynamic? false
Accept wildcard characters? false
因此,如果我们将其复制到我们自己的函数中,我们将得到:
function x
{
param
(
[Parameter(ValueFromRemainingArguments=$true)]
[Object] $Object
)
write-host $Object.GetType().FullName
write-host $Object.Count
write-host ($Object | fl * | out-string)
write-host $Object
}
现在任何未绑定的参数都捆绑到我们的 $Object
:
"Example 1"
x $aaa"bbb"
"Example 2"
x $a.b"bbb"
给出:
Example 1
System.Collections.Generic.List`1[[System.Object, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]
1
aaabbb
aaabbb
System.Collections.Generic.List`1[[System.Object, System.Private.CoreLib, Version=6.0.0.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e]]
2
aaa
bbb
aaa bbb
我们可以看到第一个示例传递了一个包含单个字符串的通用列表,write-host
简单地逐字回显,而第二个示例将任何未绑定的值捆绑到 -Output
中,它给出了一个列表其中有两个值,PowerShell 中可枚举类型的默认序列化将项目与 space 作为分隔符。