शक्तियॉं में अशक्त सहानुभूति


115

क्या पॉवरशेल में एक नल कोलेसिंग ऑपरेटर है?

मैं शब्‍दों में इन c # कमांड को करने में सक्षम होना चाहता हूं:

var s = myval ?? "new value";
var x = myval == null ? "" : otherval;

जवाबों:


133

पॉवरशेल 7+

Powershell 7 देशी null coalescing, null सशर्त असाइनमेंट और Powershell में ternary ऑपरेटरों का परिचय देता है।

अशक्त तालमेल

$null ?? 100    # Result is 100

"Evaluated" ?? (Expensive-Operation "Not Evaluated")    # Right side here is not evaluated

नल सशर्त असाइनमेंट

$x = $null
$x ??= 100    # $x is now 100
$x ??= 200    # $x remains 100

टर्नरी ऑपरेटर

$true  ? "this value returned" : "this expression not evaluated"
$false ? "this expression not evaluated" : "this value returned"

पिछला संस्करण:

पॉवरशेल सामुदायिक एक्सटेंशन के लिए कोई ज़रूरत नहीं है, यदि आप अभिव्यक्ति के रूप में बयान करते हैं, तो आप मानक पॉवरशेल का उपयोग कर सकते हैं:

variable = if (condition) { expr1 } else { expr2 }

तो आपके पहले C # अभिव्यक्ति के प्रतिस्थापन के लिए:

var s = myval ?? "new value";

निम्नलिखित में से एक बन जाता है (वरीयता के आधार पर):

$s = if ($myval -eq $null) { "new value" } else { $myval }
$s = if ($myval -ne $null) { $myval } else { "new value" }

या क्या $ myval आप उपयोग कर सकते हैं पर निर्भर करता है:

$s = if ($myval) { $myval } else { "new value" }

और दूसरा सी # अभिव्यक्ति मानचित्र इसी तरह से:

var x = myval == null ? "" : otherval;

हो जाता है

$x = if ($myval -eq $null) { "" } else { $otherval }

अब निष्पक्ष होने के लिए, ये बहुत तेज़ नहीं हैं, और कहीं भी सी # फॉर्म के रूप में उपयोग करने के लिए आरामदायक नहीं हैं।

चीजों को अधिक पठनीय बनाने के लिए आप इसे एक बहुत ही सरल कार्य में लपेटने पर विचार कर सकते हैं:

function Coalesce($a, $b) { if ($a -ne $null) { $a } else { $b } }

$s = Coalesce $myval "new value"

या संभवतः के रूप में, IfNull:

function IfNull($a, $b, $c) { if ($a -eq $null) { $b } else { $c } }

$s = IfNull $myval "new value" $myval
$x = IfNull $myval "" $otherval

जैसा कि आप देख सकते हैं एक बहुत ही सरल कार्य आपको वाक्यविन्यास की काफी स्वतंत्रता दे सकता है।

अद्यतन: मिश्रण में विचार करने के लिए एक अतिरिक्त विकल्प एक अधिक सामान्य IsTrue फ़ंक्शन है:

function IfTrue($a, $b, $c) { if ($a) { $b } else { $c } }

$x = IfTrue ($myval -eq $null) "" $otherval

फिर गठबंधन है कि शक्तियों की घोषणा करने की क्षमता है कि ऑपरेटरों की तरह एक सा लग रहे हैं, आप के साथ समाप्त:

New-Alias "??" Coalesce

$s = ?? $myval "new value"

New-Alias "?:" IfTrue

$ans = ?: ($q -eq "meaning of life") 42 $otherval

स्पष्ट रूप से यह सभी के स्वाद के लिए नहीं है, लेकिन हो सकता है कि आप जो खोज रहे हों।

थॉमस नोट के रूप में, C # संस्करण और उपरोक्त के बीच एक अन्य सूक्ष्म अंतर यह है कि C # तर्कों की लघु-परिशोधन करता है, लेकिन Powershell संस्करणों में फ़ंक्शन / उपनाम शामिल होते हैं, जो हमेशा सभी तर्कों का मूल्यांकन करेंगे। यदि यह एक समस्या है, तो ifअभिव्यक्ति फॉर्म का उपयोग करें ।


6
कोलेसिंग ऑपरेटर के बराबर एकमात्र सच एक if स्टेटमेंट का उपयोग कर रहा है; समस्या यह है कि कोई भी अन्य दृष्टिकोण शॉर्ट-सर्कुलेटिंग के बजाय सभी ऑपरेंड का मूल्यांकन करता है। "" $ myval SomeReallyExpenisveFunction () "$ myval शून्य नहीं होने पर भी फ़ंक्शन को कॉल करेगा। मुझे लगता है कि स्क्रिप्टब्लॉक का उपयोग करके मूल्यांकन में देरी हो सकती है, लेकिन ध्यान रखें कि स्क्रिप्टब्लॉक बंद नहीं होते हैं, और चीजें क्लंकी होने लगती हैं।
थॉमस एस। ट्राएस

सख्त मोड में काम नहीं करता है - यह फेंकता है The variable '$myval' cannot be retrieved because it has not been set.
BrainSlugs83

1
@ BrainSlugs83 आप जिस सख्त मोड में देख रहे हैं, वह प्रस्तुत किए गए अशक्त तालमेल विकल्पों से असंबंधित है। यह सिर्फ मानक है, पॉवरशेल जाँच रहा है कि पहले एक चर को परिभाषित किया गया है। यदि आप $myval = $nullपरीक्षण करने से पहले सेट करते हैं, तो त्रुटि दूर होनी चाहिए।
स्टीफन

1
चेतावनी, शक्तियां quirk, null की तुलना हमेशा (awkwardly) null को पहले करते हुए की जानी चाहिए, अर्थात, $null -ne $a अब अच्छा संदर्भ नहीं मिल सकता है, लेकिन यह लंबे समय तक चलने वाला अभ्यास है।
dudeNumber4

90

PowerShell 7 और बाद में

PowerShell 7 कई नई सुविधाओं का परिचय देता है और .NET फ्रेमवर्क से .NET कोर में माइग्रेट करता है। 2020 के मध्य तक, यह .NET कोर पर निर्भरता के कारण PowerShell के विरासत संस्करणों को पूरी तरह से प्रतिस्थापित नहीं करता है, लेकिन Microsoft ने संकेत दिया है कि वे कोर परिवार के लिए अंततः विरासत फ्रेमवर्क परिवार को बदलने का इरादा रखते हैं। जब आप इसे पढ़ते हैं, तब तक PowerShell का एक संगत संस्करण आपके सिस्टम पर पहले से इंस्टॉल आ सकता है; यदि नहीं, तो https://github.com/powershell/powershell देखें

प्रति प्रलेखन , निम्नलिखित ऑपरेटरों आउट-ऑफ-द-बॉक्स PowerShell 7.0 में समर्थित हैं:

  1. अशक्त-समन्वित :??
  2. अशक्त-समन्वय कार्य :??=
  3. टर्नरी :... ? ... : ...

ये काम आप अशक्त सहानुभूति की अपेक्षा करेंगे:

$x = $a ?? $b ?? $c ?? 'default value'
$y ??= 'default value'

चूँकि एक टर्नरी ऑपरेटर को पेश किया गया है, इसलिए अब यह संभव है, हालांकि यह एक अनावश्यक कोलेसिंग ऑपरेटर के अतिरिक्त दिया गया है:

$x = $a -eq $null ? $b : $a

7.0 के अनुसार, PSNullConditionalOperatorsवैकल्पिक सुविधा सक्षम होने पर निम्नलिखित भी उपलब्ध हैं , जैसा कि डॉक्स ( 1 , 2 ) में बताया गया है :

  1. सदस्यों के लिए अशक्त सदस्य की पहुंच: ?.
  2. सरणियों के लिए अशक्त-सशर्त सदस्य पहुंच एट अल: ?[]

इनमें कुछ गुहिकायन हैं:

  1. चूंकि ये प्रयोगात्मक हैं, वे परिवर्तन के अधीन हैं। जब तक आप इसे पढ़ते हैं, तब तक उन्हें प्रयोगात्मक नहीं माना जा सकता है और कैविटीज़ की सूची बदल सकती है।
  2. ${}यदि वैरिएबल नामों में प्रश्न चिह्न की अनुमति है, तो चर का उपयोग प्रायोगिक संचालकों द्वारा किया जाना चाहिए । यह स्पष्ट नहीं है कि क्या यह तब होगा जब / जब प्रायोगिक स्थिति से स्नातक की उपाधि प्राप्त हो (देखें # 11379 अंक )। उदाहरण के लिए, ${x}?.Test()नए ऑपरेटर का उपयोग करता है, लेकिन नाम के एक चर पर $x?.Test()चलता है ।Test()$x?
  3. कोई भी ?(ऑपरेटर नहीं है जैसा कि आप उम्मीद कर सकते हैं कि आप टाइपस्क्रिप्ट से आ रहे हैं। निम्नलिखित काम नहीं करेगा:$x.Test?()

पॉवरशेल 6 और पहले

7 से पहले के PowerShell संस्करणों में एक वास्तविक अशक्त सह-संचालक है, या कम से कम एक परिचालक जो इस तरह के व्यवहार के लिए सक्षम है। वह ऑपरेटर है -ne:

# Format:
# ($a, $b, $c -ne $null)[0]
($null, 'alpha', 1 -ne $null)[0]

# Output:
alpha

यह एक अशक्त coalescing ऑपरेटर की तुलना में थोड़ा अधिक बहुमुखी है, क्योंकि यह सभी गैर-शून्य वस्तुओं की एक सरणी बनाता है:

$items = $null, 'alpha', 5, 0, '', @(), $null, $true, $false
$instances = $items -ne $null
[string]::Join(', ', ($instances | ForEach-Object -Process { $_.GetType() }))

# Result:
System.String, System.Int32, System.Int32, System.String, System.Object[],
System.Boolean, System.Boolean

-eq इसी तरह काम करता है, जो शून्य प्रविष्टियों की गणना के लिए उपयोगी है:

($null, 'a', $null -eq $null).Length

# Result:
2

लेकिन वैसे भी, यहाँ C # ??ऑपरेटर के लिए एक विशिष्ट मामला है :

'Filename: {0}' -f ($filename, 'Unknown' -ne $null)[0] | Write-Output

व्याख्या

यह स्पष्टीकरण एक अनाम उपयोगकर्ता के संपादन सुझाव पर आधारित है। धन्यवाद, आप जो भी हैं!

संचालन के क्रम के आधार पर, यह निम्नलिखित क्रम में काम करता है:

  1. ,ऑपरेटर मूल्यों की एक सरणी परीक्षण किया जाना बनाता है।
  2. -neइस मामले में, अशक्त - सरणी कि निर्दिष्ट मान से मेल से किसी भी आइटम बाहर ऑपरेटर फिल्टर। परिणाम चरण 1 में बनाई गई सरणी के समान क्रम में गैर-शून्य मानों की एक सरणी है।
  3. [0] फ़िल्टर किए गए सरणी के पहले तत्व का चयन करने के लिए उपयोग किया जाता है।

सरल बनाना है कि:

  1. पसंदीदा ऑर्डर में, संभावित मानों की एक सरणी बनाएं
  2. सरणी से सभी अशक्त मानों को छोड़ दें
  3. परिणामी सरणी से पहला आइटम लें

चेतावनियां

सी # के अशक्त सहवर्ती ऑपरेटर के विपरीत, हर संभव अभिव्यक्ति का मूल्यांकन किया जाएगा, क्योंकि पहला चरण एक सरणी बनाना है।


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

यह विधि छोटी चक्कर लगाने से रोकती है। इसे देखने के लिए परिभाषित करें function DidItRun($a) { Write-Host "It ran with $a"; return $a }और चलाएं ((DidItRun $null), (DidItRun 'alpha'), 1 -ne $null)[0]
jpmc26

@ jpmc26 हां, यह डिजाइन द्वारा है।
ज़ेनेक्सर

एक मोटे समारोह को परिभाषित करने के किसी भी प्रयास से शॉर्ट सर्किटिंग को खत्म करने की संभावना नहीं है?
क्रिस एफ कैरोल

8
आह्ह्ह पॉवरशेल के संचालक पूर्वता मुझे मारते हैं! मैं हमेशा यह भूल जाता हूं कि अल्पविराम ऑपरेटर ,की इतनी उच्च प्राथमिकता है। यह कैसे काम करता है, इस पर भ्रमित किसी के लिए भी ($null, 'alpha', 1 -ne $null)[0]ऐसा ही है (($null, 'alpha', 1) -ne $null)[0]। वास्तव में उच्च precendence साथ केवल दो "पानी का छींटा" ऑपरेटर हैं -splitऔर -join(और एकल पानी का छींटा? यानी। -4या -'56')।
प्लूटो

15

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

string s = myval ?? "";

Powershell में इस प्रकार लिखा जा सकता है:

([string]myval)

या

int d = myval ?? 0;

Powershell में अनुवाद:

([int]myval)

मैं इन उपयोगी में से पहला पाया जब एक xml तत्व है कि मौजूद नहीं हो सकता है और जो अगर यह मौजूद था अवांछित व्हॉट्सएप दौर हो सकता है:

$name = ([string]$row.td[0]).Trim()

स्ट्रिंग टू स्ट्रिंग तत्व शून्य होने से बचाता है और Trim()असफल होने के जोखिम को रोकता है ।


([string]$null)-> """एक उपयोगी, लेकिन दुर्भाग्यपूर्ण साइड-इफेक्ट" जैसा लगता है :(
user2864740


9

यदि आप Powershell सामुदायिक एक्सटेंशन मॉड्यूल स्थापित करते हैं तो आप उपयोग कर सकते हैं:

?? Invoke-NullCoalescing के लिए उपनाम है।

$s = ?? {$myval}  {"New Value"}

?: Invoke-Ternary के लिए उपनाम है।

$x = ?: {$myval -eq $null} {""} {$otherval}

दरअसल, वह पॉवरशेल कमांड नहीं है। आप उन्हें pscx के साथ मिल गए:?: -> इनवोक-टर्नरी
बार्टेक

... वास्तविक कोड और परिणाम याद किया ..;) Get-Command -Module pscx -CommandType alias | जहाँ {$ _। नाम -match '\ _' } | foreach {"{0}: {1}" -f $ _। नाम, $ _। परिभाषा}?:: Invoke-Ternary ?? : आह्वान-नुल्लकोलेसिंग
बार्टेक

ओह ... आप पूरी तरह से सही हैं। मैं अक्सर यह भूल जाता हूं कि मेरे पास वह मॉड्यूल लोडिंग भी है।
ईबीग्रीन



2
function coalesce {
   Param ([string[]]$list)
   #$default = $list[-1]
   $coalesced = ($list -ne $null)
   $coalesced[0]
 }
 function coalesce_empty { #COALESCE for empty_strings

   Param ([string[]]$list)
   #$default = $list[-1]
   $coalesced = (($list -ne $null) -ne '')[0]
   $coalesced[0]
 }

2

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

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

function Coalesce([string[]] $StringsToLookThrough, [switch]$EmptyStringAsNull) {
  if ($EmptyStringAsNull.IsPresent) {
    return ($StringsToLookThrough | Where-Object { $_ } | Select-Object -first 1)
  } else {
    return (($StringsToLookThrough -ne $null) | Select-Object -first 1)
  }  
}

यह निम्नलिखित परीक्षण परिणाम उत्पन्न करता है:

Null coallesce tests:
1 (w/o flag)  - empty/null/'end'                 : 
1 (with flag) - empty/null/'end'                 : end
2 (w/o flag)  - empty/null                       : 
2 (with flag) - empty/null                       : 
3 (w/o flag)  - empty/null/$false/'end'          : 
3 (with flag) - empty/null/$false/'end'          : False
4 (w/o flag)  - empty/null/"$false"/'end'        : 
4 (with flag) - empty/null/"$false"/'end'        : False
5 (w/o flag)  - empty/'false'/null/"$false"/'end': 
5 (with flag) - empty/'false'/null/"$false"/'end': false

टेस्ट कोड:

Write-Host "Null coalesce tests:"
Write-Host "1 (w/o flag)  - empty/null/'end'                 :" (Coalesce '', $null, 'end')
Write-Host "1 (with flag) - empty/null/'end'                 :" (Coalesce '', $null, 'end' -EmptyStringAsNull)
Write-Host "2 (w/o flag)  - empty/null                       :" (Coalesce('', $null))
Write-Host "2 (with flag) - empty/null                       :" (Coalesce('', $null) -EmptyStringAsNull)
Write-Host "3 (w/o flag)  - empty/null/`$false/'end'          :" (Coalesce '', $null, $false, 'end')
Write-Host "3 (with flag) - empty/null/`$false/'end'          :" (Coalesce '', $null, $false, 'end' -EmptyStringAsNull)
Write-Host "4 (w/o flag)  - empty/null/`"`$false`"/'end'        :" (Coalesce '', $null, "$false", 'end')
Write-Host "4 (with flag) - empty/null/`"`$false`"/'end'        :" (Coalesce '', $null, "$false", 'end' -EmptyStringAsNull)
Write-Host "5 (w/o flag)  - empty/'false'/null/`"`$false`"/'end':" (Coalesce '', 'false', $null, "$false", 'end')
Write-Host "5 (with flag) - empty/'false'/null/`"`$false`"/'end':" (Coalesce '', 'false', $null, "$false", 'end' -EmptyStringAsNull)

1

निकटतम मैं प्राप्त कर सकता हूं: $Val = $MyVal |?? "Default Value"

मैंने इस तरह से ऊपर के लिए अशक्त coalescing ऑपरेटर को लागू किया :

function NullCoalesc {
    param (
        [Parameter(ValueFromPipeline=$true)]$Value,
        [Parameter(Position=0)]$Default
    )

    if ($Value) { $Value } else { $Default }
}

Set-Alias -Name "??" -Value NullCoalesc

सशर्त त्रिगुट ऑपरेटर एक similary तरह से लागू किया जा सकता।

function ConditionalTernary {
    param (
        [Parameter(ValueFromPipeline=$true)]$Value,
        [Parameter(Position=0)]$First,
        [Parameter(Position=1)]$Second
    )

    if ($Value) { $First } else { $Second }
}

Set-Alias -Name "?:" -Value ConditionalTernary

और जैसे इस्तेमाल किया: $Val = $MyVal |?: $MyVal "Default Value"

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.