我搜索了,但沒有找到如何去做。
我正在從大文件(〜2GB)過濾數據。
我使用Where-Object
,當它找到匹配時,它繼續搜索它有意義的其他匹配。如何在第一次匹配時停止管道過濾(Where-Object)
是否有可能在第一場比賽中阻止它?
例如(#1):
Get-Process | Where-Object {$_.ProcessName.StartsWith("svchost")}
輸出將是:
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
666 38 26928 18672 92 568 svchost
596 28 11516 16560 92 792 svchost
425 14 5364 7036 45 832 svchost
406 17 7032 8416 39 1004 svchost
我想要什麼是第一場比賽後返回的輸出:
Handles NPM(K) PM(K) WS(K) VM(M) CPU(s) Id ProcessName
------- ------ ----- ----- ----- ------ -- -----------
666 38 26928 18672 92 568 svchost
這就是我三ed(也用Foreach-Object):
Get-Process | Where-Object {if($_.ProcessName.StartsWith("svchost")){return $_}}
Get-Process | Where-Object {if($_.ProcessName.StartsWith("svchost")){return $_;break;}}
Get-Process | ForEach-Object {if($_.ProcessName.StartsWith("svchost")){return $_}}
但它仍然返回完整的輸出。
參考:
How to break Foreach loop in Powershell?
Is it possible to terminate or stop a PowerShell pipeline from within a filter
EDIT(約大數據的問題的解釋):
實施例(#2):
我有兩個個XML:
A.XML :
<?xml version="1.0" encoding="UTF-8"?>
<Events>
<Event>
<EventData Name="Time">09/10/2017 12:54:16</EventData>
<EventData Name="WorkstationName">USER2-PC</EventData>
<EventData Name="UserName">user2</EventData>
</Event>
</Events>
B.XML:
<?xml version="1.0" encoding="UTF-8"?>
<Events>
<Event>
<EventData Name="Time">09/10/2017 14:54:16</EventData>
<EventData Name="WorkstationName">USER1-PC</EventData>
<EventData Name="UserName">user1</EventData>
</Event>
<Event>
<EventData Name="Time">09/10/2017 13:54:16</EventData>
<EventData Name="WorkstationName">USER2-PC</EventData>
<EventData Name="UserName">user2</EventData>
</Event>
... (more 100,000 events like the above two)
</Events>
這些個XML正在加載的對象:
$fileA = "C:\tmp\A.xml"
$a = New-Object Xml.XmlDocument
$a.Load($fileA)
$fileB = "C:\tmp\B.xml"
$b = New-Object Xml.XmlDocument
$b.Load($fileB)
然後我要搜索相同的用戶名的第一場比賽:
$result = $b.Events.Event | Where-Object {
(($_.EventData | where-object {$_.Name -eq "UserName"})."#text" -eq $username)
}
$result.EventData
在這種情況下,如果我在第一個事件中匹配,則浪費時間來運行剩下的99,999個事件。
EDIT(解決):
閱讀尼克的答案後,有沒有什麼新的東西我沒有嘗試。
命令:
Get-Process | Where-Object {if($_.ProcessName.StartsWith("svchost")){ $_;break;}}
事實上停止Where-Object
,但它不返回該項目。
這可以通過解決:
Get-Process | Where-Object {if($_.ProcessName.StartsWith("svchost")){ $someVar = $_;break;}}
所以我標誌着他的答案。
'... | Where-Object {$ _。ProcessName-like'svchost *'} | Select-Object -First 1'? –
如果您正在過濾文件數據,爲什麼不使用帶有-List選項的Select-String使它在第一次匹配時停止? – mjolinor
@AnsgarWiechers它仍然會傳遞所有進程,並且在它將獲得** all **'svchost.exe'進程的對象後,它將選擇第一個進程。你可以看到它傳遞了所有的對象:'Get-Process | Where-Object {$ _。ProcessName-like'svchost *';寫主機$ _} | Select-Object-First 1' – E235