我发现使用PowerShell有一种奇怪的行为.
仅引用对象的输出与在同一对象上调用的ToString()方法的输出不同.
调用的方法或属性是什么
Write-Output "$a"
Run Code Online (Sandbox Code Playgroud)
这是我正在运行该示例的目录
> PS C:\temp\testps> DIR
Directory: C:\temp\testps
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 03/12/2010 11.21 8 1.txt
-a--- 03/12/2010 11.21 8 2.txt
-a--- 03/12/2010 11.21 8 3.txt
Run Code Online (Sandbox Code Playgroud)
在这里,我将文件集合分配给$ q对象
PS C:\temp\testps> $q = Get-ChildItem . "*.txt"
Run Code Online (Sandbox Code Playgroud)
现在我想打印文件名,但是我收到了意外的输出
PS C:\temp\testps> foreach ($a in $q) {Write-Output $a}
Directory: C:\temp\testps
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 03/12/2010 11.21 8 1.txt
-a--- 03/12/2010 11.21 8 2.txt
-a--- 03/12/2010 11.21 8 3.txt
Run Code Online (Sandbox Code Playgroud)
在对象名称周围加上引号会显示正确的行为
PS C:\temp\testps> foreach ($a in $q) {Write-Output "$a"}
1.txt
2.txt
3.txt
Run Code Online (Sandbox Code Playgroud)
这是第一个对象的输出.看起来整个DIR命令输出直到第一个文件名.非解析.
PS C:\temp\testps> foreach ($a in $q) {Write-Output $a;break}
Directory: C:\temp\testps
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 03/12/2010 11.21 8 1.txt
Run Code Online (Sandbox Code Playgroud)
ToString()方法的行为类似于引用的对象.
PS C:\temp\testps> foreach ($a in $q) {Write-Output $a.ToString()}
1.txt
2.txt
3.txt
Run Code Online (Sandbox Code Playgroud)
在第一种情况下Write-Output $a
,对象(System.IO.FileInfo)由PowerShell格式化引擎根据存储的格式数据进行格式化$pshome\FileSystem.format.ps1xml
.也就是说,真正执行的是:
Write-Output $a | Out-Default
Run Code Online (Sandbox Code Playgroud)
Out-Default在管道的末尾隐式执行,它是基于格式化数据执行格式化的cmdlet.
在这种"$a"
情况下,使用ToString()
表示.
Write-Output实际上只是将您提供给它的对象发送到pipleine中的下一个命令的一种显式方式.由于您不捕获输出,PowerShell使用对象的默认格式.这是因为Write-Output实际上并没有向stdout发送字符串,而是将对象返回到管道.第一种情况中的对象是FileSystemInfo对象的数组.
当您在PowerShell中返回数组而不捕获输出时,PowerShell会尝试迭代数组并使用其默认格式规范将每个对象显示为stdout上的文本.
因此,按照您提供的示例顺序,从dir
:
dir
返回System.Array [System.IO.FileSystemInfo].由于数组未被任何代码捕获,因此PowerShell使用其FileSystemInfo的默认格式来显示数组的内容.
同样的事情发生在上面,但是你执行迭代.实际上,您正在将自己的数组写回管道,重新构建get-childitem
首先返回的相同对象.因为,再一次,没有代码捕获输出数组对象,PowerShell就像第一种情况一样显示它.就像你写的那样:
PS C:\temp\testps> $q = Get-ChildItem . "*.txt"
PS C:\temp\testps> $children = foreach ($a in $q) {Write-Output $a}
PS C:\temp\testps> $children
Run Code Online (Sandbox Code Playgroud)
希望这清楚地表明您的示例在功能上等同于您的第一个示例.
在这里,您将$a.tostring()
在返回结果数组之前将数组中的每个对象转换为引号(告诉PowerShell调用)将其转换为字符串.所以这一次,你将一个字符串数组返回到管道.由于您没有捕获该数组,因此PowerShell会将其默认文本输出发送到控制台,如果是字符串,则只是字符串的文本.
这与情况1和2类似,因为PowerShell正在使用其FileSystemInfo对象的默认输出格式.
这与3相同,因为您再次返回一个字符串数组.唯一的区别是语义...... ToString()
当你将对象放在引号中时,你是明确地而不是隐式地调用.
有关默认格式的详细信息,请查看 help about_format
归档时间: |
|
查看次数: |
429 次 |
最近记录: |