当多个命令在脚本中使用Select-Object时,格式化问题/丢失数据 [英] Formatting issues / missing data when multiple commands use Select-Object within a script

查看:75
本文介绍了当多个命令在脚本中使用Select-Object时,格式化问题/丢失数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的PowerShell脚本遇到问题,我丢失"了要发送到控制台或被重定向的输出.经过大量的工作,我将其简化为一个易于记录的问题示例.

在脚本(test1.ps1)中放置以下单行,然后从基本的PowerShell命令窗口调用它:

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

这两个命令实际上在运行,但是第二个调用被压缩"到第一个调用的输出中.它丢失了第二列,标题和间距.

这似乎确实是第一"输出未正确关闭"的问题,因为如果将第二行传递到另一个select语句中,那么第二行到底是什么似乎并不重要.

顺便说一句,我原来的台词看起来更像这样:

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

如上所述,实际案例比这要复杂得多,但是在这一点上,我只想了解正在发生的事情.

臭虫?还是我无法理解?

解决方案

链接对其进行了更详细的说明,但是PowerShell试图在此处将您的输出分组在一起.帖子中的重要一行指出:

如果第一个Object具有2个属性,则即使流中的所有其他对象都具有10个属性,您也会获得2列表.

在以下示例中

Get-WmiObject win32_share | select name
Get-WmiObject win32_share | select name, path

运行seconds命令后,前一个命令的输出不具有该属性,因此PowerShell(更具体地说是Out-Default)将其丢弃在输出中,以使所有输出同步.

我会更奇怪您的实际代码是什么导致了此问题.就像 expirat001 所示,您可以将输出转换为字符串,并且由于它们不再是对象,因此不会发生这种情况.请谨慎操作,因为这样可能会丢失原始对象.无论哪种方式,数据都不会丢失.只是没有以您期望的方式显示.

在可以假装第一行没有path属性之前,请重新参考示例.无论如何,从select调用它只会创建null列,但将允许显示其他输出.

# 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

I've run into a problem with my PowerShell scripts where I am "losing" output that was going to the console, or being redirected. After much legwork, I simplified it down to an easily documented example of the problem.

Place the following single line in a script (test1.ps1), and invoke it from a basic PowerShell command window:

Get-WmiObject win32_share  | select name, path

and you will likely get two columns of output similar to the following:

PS C:\Users\me\temp> ./test1.ps1

name                                    path
----                                    ----
ADMIN$                                  C:\Windows
C$                                      C:\
IPC$
Users                                   C:\Users

but now, create a two line script (test2.ps1) like this, and run it in the same manner:

Get-WmiObject win32_share | select name
Get-WmiObject win32_share | select name, path

and observe the output gets mangled:

PS C:\Users\me\temp> ./test2.ps1

name
----
ADMIN$
C$
IPC$
Users
ADMIN$
C$
IPC$
Users

The two commands are actually run , but the second call gets "squeezed" into the output of the first. It lost its second column, and its header and spacing.

This really seems to be a problem of the "first" output not properly "closing out", because it really doesn't seem to matter what the second line is if it pipes into another select statement.

As an aside, my original lines looked a bit more like this:

Get-WmiObject win32_share | select name, path | Write-Output
Get-WmiObject win32_share | select name | Write-Output

So that from a powershell prompt, I could direct the output wherever I desired using redirection

PS C:\Users\me\temp\> ./test2.ps1 > ./outfile.txt

As stated, actual case is more complez than this, but at this point, I just want to get a understanding of what is happening.

Bug? Or failure to comprehend on my part?

解决方案

The link from mjolinor explains it in more detail but PowerShell is trying to group your outputs together here. An important line from the post states:

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.

In the following example

Get-WmiObject win32_share | select name
Get-WmiObject win32_share | select name, path

When the seconds command has run the output from the previous did not have that property so PowerShell, more specifically Out-Default drops it in output in order to make all the output synchronous.

I would be more curious what your real code was that was creating this issue. Like expirat001 shows you can convert the output to string and this won't happen since they are no longer objects. Be careful doing so as you can lose the original objects this way. Either way the data is not lost. Just not being displayed the way you expect.

Referring back to the example from before we can pretend the first line didn't have a path property. Calling it from select anyway would just create the null column but would allow the other output to be displayed.

# 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

This is cheating but you could sent one of the commands to a different output stream.

Get-WmiObject win32_share | select name
Get-WmiObject win32_share | select name, path | Out-Host

这篇关于当多个命令在脚本中使用Select-Object时,格式化问题/丢失数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆