当多个命令在脚本中使用 Select-Object 时格式化问题/丢失数据
Formatting issues / missing data when multiple commands use Select-Object within a script
我 运行 我的 PowerShell 脚本出现问题,我 "losing" 输出到控制台或被重定向。经过大量的跑腿工作,我将其简化为一个易于记录的问题示例。
将以下单行放在脚本中 (test1.ps1),并从基本的 PowerShell 命令中调用它 window:
Get-WmiObject win32_share | select name, path
您可能会得到两列类似于以下内容的输出:
PS C:\Users\me\temp> ./test1.ps1
name path
---- ----
ADMIN$ C:\Windows
C$ C:\
IPC$
Users C:\Users
但是现在,像这样创建一个两行脚本 (test2.ps1),然后 运行 以相同的方式创建它:
Get-WmiObject win32_share | select name
Get-WmiObject win32_share | select name, path
并观察输出被破坏:
PS C:\Users\me\temp> ./test2.ps1
name
----
ADMIN$
C$
IPC$
Users
ADMIN$
C$
IPC$
Users
这两个命令实际上是 运行 ,但是第二个调用将 "squeezed" 放入第一个的输出中。它失去了它的第二列,以及它的 header 和间距。
这似乎确实是 "first" 输出不正确 "closing out" 的问题,因为如果它通过管道传输到另一行 [=46],那么第二行似乎并不重要=]声明。
顺便说一句,我原来的台词看起来有点像这样:
Get-WmiObject win32_share | select name, path | Write-Output
Get-WmiObject win32_share | select name | Write-Output
因此,在 powershell 提示符下,我可以使用重定向将输出定向到我想要的任何地方
PS C:\Users\me\temp\> ./test2.ps1 > ./outfile.txt
如上所述,实际情况比这更复杂,但在这一点上,我只想了解正在发生的事情。
错误?还是我没看懂?
Get-WmiObject win32_share | select name | ft
Get-WmiObject win32_share | select name, path | ft
Get-WmiObject win32_share | ft name
Get-WmiObject win32_share | ft name, path
link from mjolinor 对其进行了更详细的解释,但 PowerShell 试图在此处将您的输出分组在一起。 post 中的重要一行指出:
If the first Object has 2 properties, you'll get a 2 column table even if all the other objects in the stream have 10 properties.
在下面的例子中
Get-WmiObject win32_share | select name
Get-WmiObject win32_share | select name, path
当秒命令有 运行 之前的输出没有那个 属性 所以 PowerShell,更具体地说 Out-Default
将它放在输出中,以便使所有输出同步。
我更好奇是什么代码导致了这个问题。如 所示,您可以将输出转换为字符串,这不会发生,因为它们不再是对象。这样做要小心,因为这样可能会丢失原始对象。无论哪种方式,数据都不会丢失。只是没有按照您期望的方式显示。
回顾之前的示例,我们可以假装第一行没有路径 属性。无论如何从 select
调用它只会创建空列,但会允许显示其他输出。
# In this next command "path" is not a valid property but PowerShell will create the column anyway
Get-WmiObject win32_share | select name, path
Get-WmiObject win32_share | select name, path
这是作弊,但您可以将其中一个命令发送到不同的输出流。
Get-WmiObject win32_share | select name
Get-WmiObject win32_share | select name, path | Out-Host
link from mjolinor 确实解释了很多,这里的主要问题是您通过 & ./test2.ps1
启动脚本并且 this 命令的输出是通过管道传输到 Out-Default
。反过来,Out-Default
看到由 Select-Object
cmdlet 生成的一组 PSObject
,并检查第一个对象(这是 Get-WmiObject win32_share | select name
返回的第一个对象)它发现它只有一个 属性 "name",随后从结果对象中格式化一个 table,仅收集所有对象中的 name
属性。
要规避,请使用 ft
或 Format-Table
cmdlet 将每一行的输出变成 String
序列而不是 PSObject
序列,这样当脚本的输出将通过管道传输到 Out-Default
,它将通过未处理的字符串传递。
我 运行 我的 PowerShell 脚本出现问题,我 "losing" 输出到控制台或被重定向。经过大量的跑腿工作,我将其简化为一个易于记录的问题示例。
将以下单行放在脚本中 (test1.ps1),并从基本的 PowerShell 命令中调用它 window:
Get-WmiObject win32_share | select name, path
您可能会得到两列类似于以下内容的输出:
PS C:\Users\me\temp> ./test1.ps1
name path
---- ----
ADMIN$ C:\Windows
C$ C:\
IPC$
Users C:\Users
但是现在,像这样创建一个两行脚本 (test2.ps1),然后 运行 以相同的方式创建它:
Get-WmiObject win32_share | select name
Get-WmiObject win32_share | select name, path
并观察输出被破坏:
PS C:\Users\me\temp> ./test2.ps1
name
----
ADMIN$
C$
IPC$
Users
ADMIN$
C$
IPC$
Users
这两个命令实际上是 运行 ,但是第二个调用将 "squeezed" 放入第一个的输出中。它失去了它的第二列,以及它的 header 和间距。
这似乎确实是 "first" 输出不正确 "closing out" 的问题,因为如果它通过管道传输到另一行 [=46],那么第二行似乎并不重要=]声明。
顺便说一句,我原来的台词看起来有点像这样:
Get-WmiObject win32_share | select name, path | Write-Output
Get-WmiObject win32_share | select name | Write-Output
因此,在 powershell 提示符下,我可以使用重定向将输出定向到我想要的任何地方
PS C:\Users\me\temp\> ./test2.ps1 > ./outfile.txt
如上所述,实际情况比这更复杂,但在这一点上,我只想了解正在发生的事情。
错误?还是我没看懂?
Get-WmiObject win32_share | select name | ft
Get-WmiObject win32_share | select name, path | ft
Get-WmiObject win32_share | ft name
Get-WmiObject win32_share | ft name, path
link from mjolinor 对其进行了更详细的解释,但 PowerShell 试图在此处将您的输出分组在一起。 post 中的重要一行指出:
If the first Object has 2 properties, you'll get a 2 column table even if all the other objects in the stream have 10 properties.
在下面的例子中
Get-WmiObject win32_share | select name
Get-WmiObject win32_share | select name, path
当秒命令有 运行 之前的输出没有那个 属性 所以 PowerShell,更具体地说 Out-Default
将它放在输出中,以便使所有输出同步。
我更好奇是什么代码导致了这个问题。如
回顾之前的示例,我们可以假装第一行没有路径 属性。无论如何从 select
调用它只会创建空列,但会允许显示其他输出。
# In this next command "path" is not a valid property but PowerShell will create the column anyway
Get-WmiObject win32_share | select name, path
Get-WmiObject win32_share | select name, path
这是作弊,但您可以将其中一个命令发送到不同的输出流。
Get-WmiObject win32_share | select name
Get-WmiObject win32_share | select name, path | Out-Host
link from mjolinor 确实解释了很多,这里的主要问题是您通过 & ./test2.ps1
启动脚本并且 this 命令的输出是通过管道传输到 Out-Default
。反过来,Out-Default
看到由 Select-Object
cmdlet 生成的一组 PSObject
,并检查第一个对象(这是 Get-WmiObject win32_share | select name
返回的第一个对象)它发现它只有一个 属性 "name",随后从结果对象中格式化一个 table,仅收集所有对象中的 name
属性。
要规避,请使用 ft
或 Format-Table
cmdlet 将每一行的输出变成 String
序列而不是 PSObject
序列,这样当脚本的输出将通过管道传输到 Out-Default
,它将通过未处理的字符串传递。