2012-07-23 8 views
9

मैं इस तरह कुछ करना चाहता हूँ: <filter1> के माध्यम सेक्या पावरहेल में सशर्त रूप से पाइप करना संभव है, यानी यदि कोई शर्त पूरी हो जाती है तो केवल पाइपलाइन के तत्व को निष्पादित करें?

<statement> | <filter1> | <filter2> if <condition> | <filter3> | <filter4> | <filter5> 

< बयान > रन के परिणाम, तो वे के माध्यम से <filter2> केवल < अगर हालत >, तो शेष फिल्टर के माध्यम से भले ही पूरा किया जाता है चलाने चाहे < फ़िल्टर 2 > लागू किया गया था।

if (<condition>) { 
    <statement> | <filter1> | <filter2> | <filter3> | <filter4> | <filter5> 
} else { 
    <statement> | <filter1> | <filter3> | <filter4> | <filter5> 
} 

जहां एक दिया फिल्टर परिणाम केवल सेट करते हैं तो एक निश्चित स्विच लागू किया गया था करने के लिए लागू किया जाता है यह कार्यों में उपयोगी होगा: इस के बराबर है। यदि सशर्त फ़िल्टर लंबी पाइपलाइन में जल्दी होता है, तो इसे कोड के बहुत से दोहराव में बाहरी आई-ब्लॉक परिणामों के साथ लिखना, खासकर यदि एक से अधिक सशर्त फ़िल्टर हैं।

यहां एक उदाहरण है। निम्न फ़ंक्शन किसी दिए गए खाते में दिए गए किसी भी निर्देशिका उपखंड में अनुमतियों को दिखाता है (उदा। Show-AccountPerms \\SERVERX\Marketing DOMAIN\jdoe उपयोगकर्ता डोमेन \ jdoe \ SERVERX \ मार्केटिंग के अंतर्गत निर्देशिका पेड़ में अनुमतियों की एक रिपोर्ट देता है)।

function Show-AccountPerms { 
    param (
     [parameter(mandatory = $true)]$rootdir, 
     [parameter(mandatory = $true)]$account, 
     [switch]$files, 
     [switch]$inherited 
    ) 
    gci -r $rootdir ` 
    |where {$_.psiscontainer} ` 
    |foreach { 
     $dir = $_.fullname 
     (get-acl $_.pspath).access ` 
     | where {$_.isinherited -eq 'False'} ` 
     |foreach { 
      if ($_.identityreference -eq $account) { 
       "{0,-25}{1,-35}{2}" -f $_.identityreference, $_.filesystemrights, $dir 
      } 
     } 
    } 
} 

डिफ़ॉल्ट रूप से, यह केवल स्पष्ट अनुमतियां (| where {$_.isinherited -eq 'False'} फिल्टर द्वारा लागू), और केवल निर्देशिकाओं पर (|where {$_.psiscontainer} फिल्टर द्वारा लागू) दिखाता है।

हालांकि, अगर -फाइल स्विच का आह्वान किया जाता है, तो मैं |where {$_.psiscontainer} को अनदेखा करना चाहता हूं, और | where {$_.isinherited -eq 'False'} को अनदेखा कर दूंगा। बाहरी के साथ इसे पूरा करना अगर ब्लॉक कोड को चौगुनी कर देगा, और इसमें से लगभग 75% पुनरावृत्ति होगी। क्या इन फ़िल्टरों को ऑनलाइन रखने का कोई तरीका है लेकिन केवल उन्हें संबंधित स्विच के लागू करने के लिए शक्तियों को निर्देश देना गलत है?

कृपया ध्यान दें कि यह केवल उदाहरण है, इसलिए मुझे इस फ़ंक्शन के लिए विशिष्ट किसी भी कामकाज में रूचि नहीं है। मैं सशक्त रूप से पाइपिंग के संबंध में अपने सामान्य प्रश्न का उत्तर ढूंढ रहा हूं, इस विशेष कार्य को पूरा करने के लिए समाधान नहीं।

उत्तर

3

क्षमा करें, मेरा मतलब इस प्रश्न को त्यागना नहीं था। पोस्ट किए गए उत्तरों वे नहीं थे जो मैं चला रहा था, लेकिन मुझे पोस्ट करने के कुछ ही समय बाद ऐसा करने का एक तरीका पता चला, और लंबे समय तक साइट पर वापस नहीं आया। चूंकि एक समाधान पोस्ट नहीं किया गया है, इसलिए मैं यहां आया हूं। यह काफी है कि मैं क्या मन में था जब मैं प्रश्न पूछा नहीं है और यह भी सुंदर नहीं है, लेकिन जाहिरा तौर पर यह यह करने के लिए एक ही रास्ता है:

<statement> | <filter1> | foreach {if (<condition>) {$_ | <filter2>} else {$_} | <filter3> | <filter4> | <filter5> 

तो लाइन

|where {$_.psiscontainer} ` 
, उदाहरण में,

|foreach {if (-not $files) {$_ | where {$_.psiscontainer}} else {$_}} ` 

और

|where {$_.isinherited -eq 'False'} ` 
से बदल दिया जाएगा

|foreach {if (-not $inherited) {$_ | where {$_.isinherited -eq 'False'}} else {$_}} ` 

(हाँ, सामान्य रूप से मुझे लगता है कि लिखते हैं |foreach {if ($files) {$_} else {$_ | where {$_.psiscontainer}}}, और |foreach {if ($inherited) {$_} else {$_ | where {$_.isinherited -eq 'False'}}} के रूप में लेकिन मैं यह स्पष्टता के लिए इस तरह से किया था।)

मैं वहाँ उम्मीद थी से बदल दिया जाएगा और अधिक सुरुचिपूर्ण कुछ हो सकता है , यह निर्धारित करने के लिए कि पाइपलाइन के चरण को निष्पादित या छोड़ना है, फ़िल्टर के सामने एक शर्त का मूल्यांकन करेगा।कुछ इस तरह:

<statement> | <filter1> | if (<condition>) {<filter2>} | <filter3> 

(एक if, नहीं सामान्य अर्थ के विशेष मामले; किसी अन्य कीवर्ड इस्तेमाल किया जा सकता है), या हो सकता है

<statement> | <filter1> | (<condition>) ? <filter2> | <filter3> 

$_ हालत में अमान्य हो सकता है, जब तक यह है अगर पाइप लाइन एक switch बयान के भीतर निहित है, वर्तमान पाइपलाइन के बाहर परिभाषित उदाहरण के लिए, <condition> में $_switch बयान के $_ उल्लेख करता है।

मुझे लगता है कि मैं माइक्रोसॉफ्ट के लिए एक सुविधा से संबंधित सुझाव बना देंगे। यह न केवल कोड और अधिक सुरुचिपूर्ण बनाना होगा, यह रूप में अच्छी तरह और अधिक कुशल हो सकता है, क्योंकि अगर यह एक अंतर्निहित सुविधा, <condition>एक बार पूरे पाइप लाइन के लिए मूल्यांकन किया जा सकता है, तो बजाय प्रत्येक चरण में एक ही स्वतंत्र हालत का परीक्षण।

+0

क्या आपने सुविधा अनुरोध किया है? यदि आप एक लिंक पोस्ट करते हैं तो अन्य लोग इस अनुरोध का समर्थन कर सकते हैं। –

6

आप अपने फ़िल्टर में दोनों स्थितियों के लिए परीक्षण कर सकते हैं यदि ऑब्जेक्ट पाइपलाइन को नीचे छोड़ देता है तो कोई भी सत्य है। यदि आपकी "स्थिति" -or ऑपरेटर के बाईं तरफ है, तो यदि आप अपनी फ़िल्टर स्थिति का परीक्षण नहीं करना चाहते हैं तो इसे $true पर परिणाम दें।

| where {$_.psiscontainer} 

हो जाता है::

| where {$files -or $_.psiscontainer} 

और

| where {$_.isinherited -eq 'False'} 

हो जाता है

| where {$inherited -or $_.isinherited -eq 'False'} 

अपने उदाहरण का उपयोग करने के

सामान्यीकरण करने के लिए:

<statement> | <filter1> | <filter2> if <condition> | <filter3> | <filter4> | <filter5> 

हो जाता है:

<statement> | <filter1> | <-not condition -or filter2> | <filter3> | <filter4> | <filter5> 
+1

यह फ़िल्टर ठीक है अगर फ़िल्टर एक * कहां * खंड है, लेकिन अगर फ़िल्टर स्वयं किसी शर्त का मूल्यांकन नहीं करता है, उदाहरण के लिए यदि आप 'चयन-स्ट्रिंग ' के माध्यम से ऑब्जेक्ट्स को पास करना चाहते हैं तो केवल स्थिति सही है। '| -0ot -or | 'काम नहीं करता है, उदा। '| - $ स्विच नहीं - चयन-स्ट्रिंग 'sometext' | '। ध्यान रखें कि "फ़िल्टर" का अर्थ क्या है - एक आदेश जो पाइपलाइन इनपुट लेता है और परिणामों को पाइपलाइन के नीचे भेजता है। हालत परीक्षण ** ** का हिस्सा होगा, और इसलिए केवल तभी काम करता है जब फ़िल्टर कमांड किसी शर्त का मूल्यांकन करता है (यानी, ** ** ** है)। –

4

मुझे लगता है कि इस सवाल का जवाब अन्य गलत समझती क्या कहा जा रहा है।

समाधान निम्नलिखित में निहित है:

... | %{if($_ -match "Something"){DoSomethingWith $_ }else{$_}} | ...

इस क्या करेंगे, अगले फिल्टर करने के लिए के माध्यम से सभी तत्वों को पार जाते हैं उन है कि "कुछ" से मेल है, जो मामले में यह अलग तर्क करता है सिवाय । एक फ़ंक्शन के बजाय पाइपलाइन तत्व के एक परिवर्तित संस्करण को पास करने के लिए तर्क को बदला जा सकता है।

+0

अन्य उत्तरदाता सही ढंग से समझ गए। विचार प्रत्येक वस्तु को एक शर्त लागू नहीं करना है और यह इस शर्त के आधार पर अलग-अलग प्रक्रिया करता है कि यह स्थिति को पूरा करता है या नहीं; यह एक ऐसी स्थिति का परीक्षण करना है जो * पाइपलाइन * में ऑब्जेक्ट्स से स्वतंत्र है और * सभी * ऑब्जेक्ट्स पर फ़िल्टर लागू करें, लेकिन * केवल अगर * शर्त सही है - ** ** ** का उपयोग करने के बराबर पाइपलाइन निष्पादित करने के लिए मंच, लेकिन बहुत सारे कोड दोहराए बिना। मेरे उदाहरण में, ** $ फ़ाइलें ** कुछ ऐसा नहीं है जो प्रत्येक ऑब्जेक्ट से तुलना की जाती है, यह एक साधारण स्विच है जो यह निर्धारित करता है कि सभी ऑब्जेक्ट्स या किसी भी पर एक फ़िल्टर लागू किया जाएगा या नहीं। –

+0

हालांकि, यह उत्तर उपयोगी था कि यह ** अन्य ** ब्लॉक होने का विचार पेश करता है यदि कोई शर्त पूरी नहीं हुई है तो बस सभी ऑब्जेक्ट्स को गूंजें। विचार 'अगर (<शर्त है कि $ _> के साथ कुछ भी नहीं है) {{इस फ़िल्टर के माध्यम से पाइप $ _>}, अन्यथा इस फ़िल्टर को छोड़ दें और पाइपलाइन के अगले चरण पर जाएं। 'Else {$ _}' प्रभावी रूप से उस अंतिम भाग के लिए एक कामकाज है, पाइपलाइन के चरण को छोड़कर और अगले स्थान पर जा रहा है। –

1

मुझे लगता है कि आप निम्नलिखित है, जो मैं अभी ही गाढ़ा तरह कुछ मतलब: 2 में

function Pipe-If([ScriptBlock]$decider, [ScriptBlock]$pipeElement) 
{ 
    if (&$decider) { 
     $pipeElement 
    } else { 
     {$input} 
    } 
} 

@(1,2,3) | &(Pipe-If {$doDouble} {$input | % { $_ * 2} }) 

परिणाम, 4, 6, तो $doDouble है $true, और $false पर यह 1, 2, 3 में परिणाम ।

कुंजी है कि यहाँ % { $_ * 2} की तरह एक मनमाना पाइप तत्व {$input | % { $_ * 2 } } के रूप में एक ScriptBlock के रूप में समझाया जा सकता है, और कहा कि इसे वापस एक पाइप तत्व को & prepending द्वारा परिवर्तित किया जा सकता है।

मैं प्रेरणा के लिए http://blogs.msdn.com/b/powershell/archive/2006/12/29/dyi-ternary-operator.aspx इस्तेमाल किया।


महत्वपूर्ण नोट। कुछ इस तरह का प्रयोग न करें:

filter Incorrect-Pipe-If([ScriptBlock]$decider, [ScriptBlock]$pipeElement) { 
    if (&$decider) { 
     $_ | &$pipeElement 
    } else { 
     $_ 
    } 
} 

@(1,2,3) | Incorrect-Pipe-If {$doDouble} {$_ | % { $_ * 2} } 

इस कारण % एक बार पाइप लाइन में प्रत्येक वस्तु के लिए कई बार निष्पादित करने के लिए,। Pipe-If ठीक से एक बार % आदेश निष्पादित करता है, और इसे ऑब्जेक्ट्स की पूरी स्ट्रीम भेजता है।

उपर्युक्त उदाहरण में यह कोई समस्या नहीं है। लेकिन अगर आदेश tee bla.txt है तो अंतर महत्वपूर्ण है।

+0

यह मुझे एक ही समाधान के रूप में अनिवार्य रूप से एक ही समाधान (वर्कअराउंड, वास्तव में, क्योंकि यह वही नहीं है जो मुझे चाहिए) जैसा दिखता है, सिवाय इसके कि यह एक फ़ंक्शन में लपेटा गया है। मैं इसे विपरीत दिशा में एक कदम के रूप में देखता हूं, क्योंकि न केवल कोड को महत्वपूर्ण रूप से कॉम्पैक्ट किए बिना बाहरी कार्य की उपलब्धता पर भरोसा करता है, यह वास्तव में इसे कम कुशल बनाता है, क्योंकि प्रत्येक पुनरावृत्ति के लिए स्थिति का अभी भी मूल्यांकन किया जाता है, लेकिन अब यह एक ही तर्क को निष्पादित करने के लिए बाहरी कार्यात्मक कॉल करता है। –

+0

@AdiInbar आप पूछ रहे थे, "क्या इन फ़िल्टरों को ऑनलाइन रखने का कोई तरीका है लेकिन उन्हें केवल इसी स्विच के लागू करने के लिए शक्तियों को निर्देश देना गलत है?" और आपने कहा कि आप "कुछ अधिक सुरुचिपूर्ण" की तलाश में हैं, जो यह निर्धारित करने के लिए फ़िल्टर के सामने एक शर्त का मूल्यांकन करेगा कि पाइपलाइन के चरण को निष्पादित या छोड़ना है या नहीं। " मेरा 'और (पाइप-अगर {} {$ _ | }) 'बिल्कुल ऐसा वाक्यविन्यास है। फ़ंक्शन का उपयोग करना है या नहीं (संभावित रूप से कोई प्रदर्शन प्रभाव नहीं) संदर्भ पर निर्भर करता है, और क्या कोई 'foreach {pre () {$ _ | } अन्य {$ _} 'वरीयता है। –

0

एक अन्य विकल्प (प्रकार System.Management.Automation.ActionPreference की) एक वैश्विक वरीयता झंडा उपयोग करने के लिए उपयोगकर्ता निर्धारित करने के लिए पाइप लाइन फिल्टर कुछ करता है अनुमति है।

उदाहरण के लिए, $progressPreference निम्न मान के लिए सेट किया जा सकता है:

  • SilentlyContinue
  • बंद करो
  • जारी
  • पूछताछ
  • पर ध्यान न दें

यह वरीयता झंडा है फिरद्वारा उपयोग किया जाता है वांछित व्यवहार निर्धारित करने के लिए।

उदाहरण के लिए, यदि आप एक पाइप लाइन फिल्टर Show-Progress, कि आइटम में गिना जाता है और एक प्रगति बार प्रदर्शित करती है, तो यह केवल इस प्रगति बार जब $progressPreferenceContinue पर सेट है प्रदर्शित करेगा।

आप अपने पाइपलाइन फ़िल्टर में सिमुलेटर निर्माण का उपयोग कर सकते हैं।

+0

मुझे यकीन नहीं है कि आप क्या कहने की कोशिश कर रहे हैं, लेकिन ऐसा लगता है कि आप इस सवाल को गलत तरीके से पढ़ते हैं, क्योंकि यह बिल्कुल संबंधित नहीं प्रतीत होता है। यह इंटरेक्टिव यूजर फैसले, प्रोग्रेस बार, या एरर हैंडलिंग के बारे में नहीं है, यह पाइपलाइन के एक सेक्शन को निष्पादित करने के बारे में है यदि कोई दी गई स्वतंत्र स्थिति सही है और अगर स्थिति गलत है तो उस सेक्शन को छोड़ दें। "स्वतंत्र" से मेरा मतलब है कि पाइपलाइन वस्तुओं की सामग्री पर आधारित नहीं है, यानी यदि स्थिति सत्य है, तो वह अनुभाग सभी वस्तुओं के लिए निष्पादित किया जाता है; यदि गलत है, तो यह किसी ऑब्जेक्ट के लिए निष्पादित नहीं है। –

+0

@AdiInbar मूल प्रश्न को निष्पादन से पाइपलाइनों को छोड़ने के लिए एक समाधान की आवश्यकता होती है, यह एक परिदृश्य को ठीक से करने के लिए वर्णन करता है, और जटिल कोड निर्माण का उपयोग किए बिना। आपका भ्रम क्या है? –

+0

मैं उम्मीद कर रहा था कि इसे "इनलाइन" करने का कोई तरीका नहीं था, प्रत्येक पुनरावृत्ति पर पुन: मूल्यांकन करने की आवश्यकता के बिना, एक ऐसी स्थिति जो पाइपलाइन की अवधि के लिए अपरिवर्तनीय है। ऐसा संभव नहीं लगता है। मैं इसे एक फीचर अनुरोध के रूप में प्रस्तुत कर सकता हूं। –

संबंधित मुद्दे

 संबंधित मुद्दे