Powershell:if 语句中的管道变量 $_?
Powershell: Pipe variable $_ in if statement?
我有以下简短的脚本来获取 OU 中计算机和显示器的序列号,效果很好:
Import-Module ActiveDirectory
$searchbase = "OU=some,OU=organisational,OU=units,DC=somedomain,DC=local"
Write-Host ""
Write-Host "Serial Numbers for Computers and Monitors in" $searchbase
Write-Host "--"
Get-ADComputer -SearchBase $searchbase -Filter '*' | `
Select-Object -Expand Name | %{Write-Host ""; echo $_ ; Get-WMIObject -Class Win32_BIOS -ComputerName $_ | Select-Object -Expand SerialNumber; `
$monitor = gwmi WmiMonitorID -Namespace root\wmi -computername $_; ($monitor.SerialNumberID | foreach {[char]$_}) -join ""};
此脚本在尝试获取 WMIObject 之前不会检查计算机是否在线,因此如果计算机处于离线状态,则 RPC 调用超时之前需要很长时间。
在尝试获取 WMIObject 之前,我尝试修改脚本以使用 Test-Connection cmdlet:
Import-Module ActiveDirectory
$searchbase = "OU=some,OU=organisational,OU=units,DC=somedomain,DC=local"
Write-Host ""
Write-Host "Serial Numbers for Computers and Monitors in" $searchbase
Write-Host "--"
Get-ADComputer -SearchBase $searchbase -Filter '*' | `
Select-Object -Expand Name | `
if (Test-Connection -ComputerName $_ -Quiet) {
%{Write-Host ""; echo $_ ; Get-WMIObject -Class Win32_BIOS -ComputerName $_ | Select-Object -Expand SerialNumber; `
$monitor = gwmi WmiMonitorID -Namespace root\wmi -computername $_; ($monitor.SerialNumberID | foreach {[char]$_}) -join ""};}
}
else {
Write-Host ""; Write-Host $_ "is offline";
}
我确定我在做一些语法上愚蠢的事情。有人能指出我正确的方向吗?
您不能直接传送到 if
语句,只能传送到 cmdlet。
将 if
语句 放在 块 ForEach-Object
中(%
是 ForEach-Object
的别名):
... | Select-Object -Expand Name | `
%{
if (Test-Connection -ComputerName $_ -Quiet) {
# Get-WmiObject in here
}
else {
Write-Host ""; Write-Host $_ "is offline";
}
}
如果您不关心将每台机器的状态写入主机,您还可以通过 Where-Object
(alias ?
):
过滤掉离线计算机
... | Select-Object -Expand Name | ?{
Test-Connection $_ -Quiet
} | % {
Get-WmiObject -ComputerName $_
}
除了@Mathias R. Jessen 的回答之外,您还可以去掉续行的反引号。
如果行尾推断语句需要另一个代码块,则不需要它们。喜欢 |
或 {
或 (
.
"foo", "bar" |
% {$_}
工作正常...
我有以下简短的脚本来获取 OU 中计算机和显示器的序列号,效果很好:
Import-Module ActiveDirectory
$searchbase = "OU=some,OU=organisational,OU=units,DC=somedomain,DC=local"
Write-Host ""
Write-Host "Serial Numbers for Computers and Monitors in" $searchbase
Write-Host "--"
Get-ADComputer -SearchBase $searchbase -Filter '*' | `
Select-Object -Expand Name | %{Write-Host ""; echo $_ ; Get-WMIObject -Class Win32_BIOS -ComputerName $_ | Select-Object -Expand SerialNumber; `
$monitor = gwmi WmiMonitorID -Namespace root\wmi -computername $_; ($monitor.SerialNumberID | foreach {[char]$_}) -join ""};
此脚本在尝试获取 WMIObject 之前不会检查计算机是否在线,因此如果计算机处于离线状态,则 RPC 调用超时之前需要很长时间。
在尝试获取 WMIObject 之前,我尝试修改脚本以使用 Test-Connection cmdlet:
Import-Module ActiveDirectory
$searchbase = "OU=some,OU=organisational,OU=units,DC=somedomain,DC=local"
Write-Host ""
Write-Host "Serial Numbers for Computers and Monitors in" $searchbase
Write-Host "--"
Get-ADComputer -SearchBase $searchbase -Filter '*' | `
Select-Object -Expand Name | `
if (Test-Connection -ComputerName $_ -Quiet) {
%{Write-Host ""; echo $_ ; Get-WMIObject -Class Win32_BIOS -ComputerName $_ | Select-Object -Expand SerialNumber; `
$monitor = gwmi WmiMonitorID -Namespace root\wmi -computername $_; ($monitor.SerialNumberID | foreach {[char]$_}) -join ""};}
}
else {
Write-Host ""; Write-Host $_ "is offline";
}
我确定我在做一些语法上愚蠢的事情。有人能指出我正确的方向吗?
您不能直接传送到 if
语句,只能传送到 cmdlet。
将 if
语句 放在 块 ForEach-Object
中(%
是 ForEach-Object
的别名):
... | Select-Object -Expand Name | `
%{
if (Test-Connection -ComputerName $_ -Quiet) {
# Get-WmiObject in here
}
else {
Write-Host ""; Write-Host $_ "is offline";
}
}
如果您不关心将每台机器的状态写入主机,您还可以通过 Where-Object
(alias ?
):
... | Select-Object -Expand Name | ?{
Test-Connection $_ -Quiet
} | % {
Get-WmiObject -ComputerName $_
}
除了@Mathias R. Jessen 的回答之外,您还可以去掉续行的反引号。
如果行尾推断语句需要另一个代码块,则不需要它们。喜欢 |
或 {
或 (
.
"foo", "bar" |
% {$_}
工作正常...