Powershell 似乎将 select cmdlet 绑定到默认输出流,并且在命令完成后不释放它,从而以意想不到的方式影响未来的命令。它如何做到这一点并不一致,这使得在编写脚本时如果没有明确指示输出就不可能生成可预测的输出。
如果您将命令放在不同的行上,混合使用不同的对象生成 cmdlet 等,就会发生这种奇怪的情况。如果您以交互方式在不同的行上运行命令,则不会发生这种情况,并且在命令行上自动创建的对象也不会发生这种情况,除非您混合在命令行上未自动创建的对象。
我给出了命令行交互式示例,但是如果您将这些命令放入一个脚本中,每个命令位于一个单独的行上,然后运行该脚本,就会发生这种情况。
PS /home/dennis> get-date|select dayofweek ; get-date
DayOfWeek
---------
Monday
Monday
PS /home/dennis> "string1"|select length ; "string2"
Length
------
7
string2
为了好玩,看看这个:
S /home/dennis> "string0" ;"string1"|select length ; get-host ;"string2" ;get-date; 567 ; get-host
string0
Length
------
7
1
string2
1
567
1
PS /home/dennis> cat test.ps1
"string0"
"string1"|select length
get-host
"string2"
get-date
567
(1..5)
get-host
PS /home/dennis> ./test.ps1
string0
Length
------
7
1
string2
1
567
1
2
3
4
5
1
...
这也会影响不同类型的对象,事实上,它会影响甚至没有 select 语句中的属性的对象。延迟不是一个选项,使用 out-host 或 write-host 显式强制输出将直接写入 powershell 输出设备,因此创建将用于在管道中生成对象的脚本毫无用处。它也会混淆变量。观察:
PS /home/dennis> $d = get-date | select dayofweek ; $e = get-date ; $d ; $e
DayOfWeek
---------
Monday
Monday
PS /home/dennis> $d
DayOfWeek
---------
Monday
PS /home/dennis> $e
Monday, August 5, 2019 12:33:47 PM
对于那些正在思考的人来说,这只是一个显示问题,并且可以编写脚本以正确显示它,我再说一遍,这使得脚本作为您可以在其他脚本中重复使用的工具毫无用处。观察脚本中的管道如何影响独立交互式 shell 中的命令。
PS /home/dennis> cat test.ps1
"string0"
"string1"|select length
get-host
"string2"
get-date
567
get-host
PS /home/dennis> ./test.ps1|% {$_}
string0
Length
------
7
1
string2
1
567
1
PS /home/dennis> ./test.ps1|% {write-host $_}
string0
@{Length=7}
System.Management.Automation.Internal.Host.InternalHost
string2
8/5/19 12:50:54 PM
567
System.Management.Automation.Internal.Host.InternalHost
PS /home/dennis> ./test.ps1|% {$_|out-host}
string0
Length
------
7
Name : ConsoleHost
Version : 6.2.2
InstanceId : 4e46c643-1a9d-4c55-9151-b311f287a9cb
UI : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture : en-US
CurrentUICulture : en-US
PrivateData : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
DebuggerEnabled : True
IsRunspacePushed : False
Runspace : System.Management.Automation.Runspaces.LocalRunspace
string2
Monday, August 5, 2019 1:20:24 PM
567
Name : ConsoleHost
Version : 6.2.2
InstanceId : 4e46c643-1a9d-4c55-9151-b311f287a9cb
UI : System.Management.Automation.Internal.Host.InternalHostUserInterface
CurrentCulture : en-US
CurrentUICulture : en-US
PrivateData : Microsoft.PowerShell.ConsoleHost+ConsoleColorProxy
DebuggerEnabled : True
IsRunspacePushed : False
Runspace : System.Management.Automation.Runspaces.LocalRunspace
在任何 shell 脚本中,我希望一个命令将独立于前一个命令执行。WhatTheFortran 是这种行为背后的逻辑?避免这种不可预测性的官方建议是什么?