के भीतर से एक PowerShell पाइपलाइन रोक मैं एक साधारण PowerShell फिल्टर है कि पाइप लाइन नीचे मौजूदा वस्तु धक्का अगर इसकी तिथि निर्दिष्ट शुरू और अंत तिथि के बीच है लिखा है करने के लिए है। पाइपलाइन के नीचे आने वाली वस्तुएं हमेशा आरोही तिथि क्रम में होती हैं, जैसे ही तिथि निर्दिष्ट समाप्ति तिथि से अधिक हो जाती है, मुझे पता है कि मेरा काम पूरा हो गया है और मैं पाइपलाइन को बताना चाहता हूं कि अपस्ट्रीम कमांड उनके काम को त्याग सकते हैं ताकि पाइपलाइन अपना काम खत्म कर सकते हैं। मैं कुछ बहुत बड़ी लॉग फाइलें पढ़ रहा हूं और मैं अक्सर लॉग के केवल एक हिस्से की जांच करना चाहता हूं। मुझे पूरा यकीन है कि यह संभव नहीं है लेकिन मैं निश्चित रूप से पूछना चाहता हूं।यह संभव समाप्त या एक फिल्टर
उत्तर
यह एक नीचे की ओर आदेश से एक नदी के ऊपर आदेश को रोकने के लिए संभव नहीं है .. यह वस्तुओं आपके मानदंड से मेल नहीं खाते को फिल्टर करने के लिए जारी रहेगा, लेकिन पहले आदेश सब कुछ इसे संसाधित करने में स्थापित किया गया था पर कार्रवाई करेंगे।
वर्कअराउंड अपस्ट्रीम cmdlet या फ़ंक्शन/फ़िल्टर पर अधिक फ़िल्टरिंग करना होगा। लॉग फाइलों के साथ काम करना इसे थोड़ा अधिक कॉम्पोप्लिकेट बनाता है, लेकिन शायद चयन-स्ट्रिंग का उपयोग करके और अवांछित तिथियों को फ़िल्टर करने के लिए नियमित अभिव्यक्ति आपके लिए काम कर सकती है।
जब तक आप जानते हैं कि कैसे कई लाइनों लेने के लिए और जहां से, पूरी फ़ाइल पैटर्न के लिए जाँच करने के लिए पढ़ा जाएगा चाहते हैं।
इन फिल्टर का प्रयास करें, वे -या पहले n तत्व पहली वस्तु के बाद बंद करो और यह एक चर में -them- स्टोर करने के लिए पाइप लाइन के लिए मजबूर करेंगे; यदि आप ऑब्जेक्ट को धक्का नहीं देते हैं तो आपको चर के नाम को पास करने की आवश्यकता है, लेकिन एक चर को असाइन नहीं किया जा सकता है।
filter FirstObject ([string]$vName = '') {
if ($vName) {sv $vName $_ -s 1} else {$_}
break
}
filter FirstElements ([int]$max = 2, [string]$vName = '') {
if ($max -le 0) {break} else {$_arr += ,$_}
if (!--$max) {
if ($vName) {sv $vName $_arr -s 1} else {$_arr}
break
}
}
# can't assign to a variable directly
$myLog = get-eventLog security | ... | firstObject
# pass the the varName
get-eventLog security | ... | firstObject myLog
$myLog
# can't assign to a variable directly
$myLogs = get-eventLog security | ... | firstElements 3
# pass the number of elements and the varName
get-eventLog security | ... | firstElements 3 myLogs
$myLogs
####################################
get-eventLog security | % {
if ($_.timegenerated -lt (date 11.09.08) -and`
$_.timegenerated -gt (date 11.01.08)) {$log1 = $_; break}
}
#
$log1
यकीन है, लेकिन यह Log Parser को देखने के लिए यदि आप डेटा फ़िल्टर कर देती है तो यह और भी पाइप हिट एक प्रश्न उपयोग नहीं कर सकते देखने के लिए अपने समय के लायक हो सकता है।
एक अन्य विकल्प switch
बयान पर -file
पैरामीटर का उपयोग करना होगा। -file
का उपयोग एक समय में फ़ाइल को एक पंक्ति में पढ़ेगा, और आप शेष फ़ाइल को पढ़ने के बिना तत्काल बाहर निकलने के लिए break
का उपयोग कर सकते हैं।
switch -file $someFile {
# Parse current line for later matches.
{ $script:line = [DateTime]$_ } { }
# If less than min date, keep looking.
{ $line -lt $minDate } { Write-Host "skipping: $line"; continue }
# If greater than max date, stop checking.
{ $line -gt $maxDate } { Write-Host "stopping: $line"; break }
# Otherwise, date is between min and max.
default { Write-Host "match: $line" }
}
पाइपलाइन समाप्त करते समय आप अपवाद फेंक सकते हैं।
gc demo.txt -ReadCount 1 | %{$num=0}{$num++; if($num -eq 5){throw "terminated pipeline!"}else{write-host $_}}
या कैसे एक पाइप लाइन को समाप्त करने के बारे में इस पोस्ट पर
देखो:
http://powershell.com/cs/blogs/tobias/archive/2010/01/01/cancelling-a-pipeline.aspx
यह कुछ भी साथ एक पाइप लाइन है कि अन्यथा एक बाहर पाश या पड़ाव स्क्रिप्ट निष्पादन टूट जाएगा तोड़ने के लिए संभव है पूरी तरह से (एक अपवाद फेंकने की तरह)। समाधान तब पाइपलाइन को एक लूप में लपेटना है जिसे आप पाइपलाइन को रोकने की जरूरत है तो आप तोड़ सकते हैं।उदाहरण के लिए, नीचे दिए गए कोड पाइपलाइन से पहले आइटम वापस आ जाएगी और उसके बाद बाहर कर-जबकि पाश तोड़कर पाइप लाइन तोड़:
do {
Get-ChildItem|% { $_;break }
} while ($false)
यह कार्यक्षमता इस तरह एक समारोह है, जहां अंतिम पंक्ति में लपेटा जा सकता है एक ही बात के रूप में ऊपर पूरा करता: - अपूर्ण -
function Breakable-Pipeline([ScriptBlock]$ScriptBlock) {
do {
. $ScriptBlock
} while ($false)
}
Breakable-Pipeline { Get-ChildItem|% { $_;break } }
यहाँ एक है एक Stop-Pipeline
cmdlet के कार्यान्वयन (की आवश्यकता है पुनश्च v3 +), कृतज्ञता this answer से अनुकूलित:
#requires -version 3
Filter Stop-Pipeline {
$sp = { Select-Object -First 1 }.GetSteppablePipeline($MyInvocation.CommandOrigin)
$sp.Begin($true)
$sp.Process(0)
}
# Example
1..5 | % { if ($_ -gt 2) { Stop-Pipeline }; $_ } # -> 1, 2
कैविट: मैं पूरी तरह से समझ नहीं पा रहा हूं कि यह कैसे काम करता है, हालांकि मूल रूप से यह Select -First
की पाइपलाइन को समय-समय पर रोकने की क्षमता का लाभ उठाता है (पीएस v3 +)। नीचे की ओर cmdlets (बाद में आदेश पाइप लाइन में) उनके end
ब्लॉकों को चलाने के लिए एक मौका नहीं मिलता है: हालांकि, इस मामले में कैसे Select -First
पाइपलाइन समाप्त हो जाता है के लिए एक महत्वपूर्ण अंतर है।
इसलिए, एकत्रित cmdlets (उन है कि उत्पादन के उत्पादन से पहले सभी इनपुट प्राप्त करना चाहिए, इस तरह के Sort-Object
, Group-Object
, और Measure-Object
के रूप में) उत्पादन का उत्पादन नहीं होगा अगर एक ही पाइप लाइन में बाद में रखा; उदा .:
# !! NO output, because Sort-Object never finishes.
1..5 | % { if ($_ -gt 2) { Stop-Pipeline }; $_ } | Sort-Object
पृष्ठभूमि की जानकारी है कि एक बेहतर समाधान को जन्म दे सकती: PetSerAl को
धन्यवाद, मेरी answer here पता चलता है कि Select-Object -First
आंतरिक रूप से उपयोग करता है नदी के ऊपर cmdlets को रोकने के लिए एक ही अपवाद निर्माण करने के लिए।
हालांकि, वहाँ अपवाद cmdlet अंदर से फेंक दिया जाता है ही पाइप लाइन से जुड़ा को रोकने के लिए है, इसमें वे यहाँ मामला नहीं है: के रूप में ऊपर के उदाहरण में इस्तेमाल किया,
Stop-Pipeline
, नहीं है पाइपलाइन से जुड़ा हुआ है जिसे रोकना चाहिए (केवल ForEach-Object
(%
) ब्लॉक संलग्न है), इसलिए सवाल यह है कि लक्ष्य पाइपलाइन के संदर्भ में अपवाद कैसे फेंक दिया जा सकता है?
गैर-सार्वजनिक सदस्यों का उपयोग करके ऐसा करने के लिए मेरे उत्तर को देखें। –
यदि आप गैर-सार्वजनिक सदस्यों का उपयोग करने के इच्छुक हैं तो पाइपलाइन को रोकने का एक तरीका है। यह नकल करता है कि select-object
क्या करता है। invoke-method
(उपनाम im
) गैर-सार्वजनिक तरीकों का आह्वान करने के लिए एक कार्य है। select-property
(उर्फ selp
) गैर-सार्वजनिक गुणों का चयन करने के लिए एक फ़ंक्शन (चयन-ऑब्जेक्ट के समान) है - हालांकि यह स्वचालित रूप से -ExpandProperty
जैसा कार्य करता है यदि केवल एक मिलान करने वाली संपत्ति पाई जाती है। (मैंने काम पर select-property
और invoke-method
लिखा था, इसलिए उनमें से स्रोत कोड साझा नहीं कर सकते हैं)।
# Get the system.management.automation assembly
$script:smaa=[appdomain]::currentdomain.getassemblies()|
? location -like "*system.management.automation*"
# Get the StopUpstreamCommandsException class
$script:upcet=$smaa.gettypes()| ? name -like "*StopUpstreamCommandsException *"
function stop-pipeline {
# Create a StopUpstreamCommandsException
$upce = [activator]::CreateInstance($upcet,@($pscmdlet))
$PipelineProcessor=$pscmdlet.CommandRuntime|select-property PipelineProcessor
$commands = $PipelineProcessor|select-property commands
$commandProcessor= $commands[0]
$ci = $commandProcessor|select-property commandinfo
$upce.RequestingCommandProcessor | im set_commandinfo @($ci)
$cr = $commandProcessor|select-property commandruntime
$upce.RequestingCommandProcessor| im set_commandruntime @($cr)
$null = $PipelineProcessor|
invoke-method recordfailure @($upce, $commandProcessor.command)
if ($commands.count -gt 1) {
$doCompletes = @()
1..($commands.count-1) | % {
write-debug "Stop-pipeline: added DoComplete for $($commands[$_])"
$doCompletes += $commands[$_] | invoke-method DoComplete -returnClosure
}
foreach ($DoComplete in $doCompletes) {
$null = & $DoComplete
}
}
throw $upce
}
संपादित करें: mklement0 की टिप्पणी प्रति:
यहाँ "प्रहार" मॉड्यूल जो इसी तरह गैर सरकारी सदस्यों के लिए पहुँच देता है पर एक स्क्रिप्ट पर Nivot स्याही ब्लॉग में एक link है।
जहां तक अतिरिक्त टिप्पणियां हैं, मेरे पास इस बिंदु पर सार्थक नहीं हैं। यह कोड सिर्फ नकल करता है कि select-object
का एक अपघटन क्या प्रकट करता है। मूल एमएस टिप्पणियां (यदि कोई हैं) निश्चित रूप से अपघटन में नहीं हैं। स्पष्ट रूप से मैं फ़ंक्शन का उपयोग करने वाले विभिन्न प्रकारों के उद्देश्य को नहीं जानता हूं। समझने के उस स्तर को प्राप्त करने के लिए काफी प्रयास की आवश्यकता होगी।
मेरा सुझाव: ओसीन के पॉक मॉड्यूल प्राप्त करें। उस मॉड्यूल का उपयोग करने के लिए कोड को ट्विक करें। और फिर इसे आज़माएं। यदि आप जिस तरह से काम करते हैं उसे पसंद करते हैं, तो इसका इस्तेमाल करें और चिंता न करें कि यह कैसे काम करता है (यही वह है जो मैंने किया)।
नोट: मैंने किसी भी गहराई में "पोक" का अध्ययन नहीं किया है, लेकिन मेरा अनुमान है कि इसमें -returnClosure
जैसी कोई चीज़ नहीं है। हालांकि यह भी कहा कि इस के रूप में आसान होना चाहिए: -: दरअसल:
if (-not $returnClosure) {
$methodInfo.Invoke($arguments)
} else {
{$methodInfo.Invoke($arguments)}.GetNewClosure()
}
प्रभावशाली, लेकिन दिमागी झुकाव। यदि आप इसके लिए तैयार हैं, तो शायद आप अधिक टिप्पणियां जोड़ सकते हैं और यह भी इंगित कर सकते हैं कि अन्य लोग 'चयन-संपत्ति' और 'आमंत्रण-विधि' के अपने संस्करणों को कैसे कार्यान्वित कर सकते हैं। – mklement0
यह एक पाश में काम नहीं करता है को तोड़ने पाश को रोकने के लिए भी –
@DavidGardiner लगता है 'break' और' CONTINUE' _not_ बाहर निकलने के लिए तैयार कर रहे हैं पाइपलाइन, वे _loops_ (और 'स्विच' शाखाओं) से बाहर तोड़ते हैं। यदि कोई संलग्न लूप नहीं है, तो केवल एक चीज होती है कि यह कार्य बाहर निकलता है - जो एक दुष्प्रभाव के रूप में पाइपलाइन को समाप्त करता है। यदि वहां एक संलग्न लूप _is_ है, तो तदनुसार 'ब्रेक' और 'जारी रखें' कार्य करें, जो अप्रत्याशित हो सकता है। एक सरल, लेकिन नाजुक और असुविधाजनक कामकाज एक डमी लूप में आमंत्रण को लपेटना है, जैसा कि [@ अधिकतमकुकी के उत्तर] (http://stackoverflow.com/a/30943992/45375) में है। – mklement0