powershell - मैं कमांड लाइन पर मानों की एक सीमा कैसे पार करूं-एक अभिव्यक्ति को एक तर्क के रूप में पारित करना



parsing command-line (1)

आपकी समस्या यह है कि तर्क 29..30+40+50..52 को आपके में एक स्ट्रिंग शाब्दिक के रूप में माना जाता है .\eraseme.ps1 29..30+40+50..52 कॉल - यह एक अभिव्यक्ति के रूप में मान्यता प्राप्त नहीं है

एक अभिव्यक्ति के रूप में मान्यता को मजबूर करने के लिए , बस (...) में तर्क को संलग्न करें :

.\eraseme.ps1 (29..30+40+50..52)

ध्यान दें कि आप अपने पैरामीटर को अधिक विशिष्ट प्रकार के साथ घोषित करके अपनी स्क्रिप्ट को और अधिक मजबूत बना सकते हैं, इस स्थिति में इसे स्ट्रिंग के साथ कॉल करने का प्रयास तुरंत विफल हो जाएगा:

 [Parameter(Mandatory=$False)] [int[]] $srv_range

(अन्य अनुकूलन आपकी स्क्रिप्ट पर भी लागू किए जा सकते हैं।)

वैकल्पिक पृष्ठभूमि की जानकारी

जब तक एक निर्विवाद टोकन को तर्क विधा में एक बनाम (एक्सपेंडेबल) स्ट्रिंग के रूप में माना जाता है ( about_Parsing ):

  • (...) , $(...) , और @(...) स्वयं या टोकन के प्रारंभ में एक नया पार्सिंग संदर्भ बनाते हैं , जिसमें भाव या नेस्टेड कमांड का भी उपयोग किया जा सकता है:

    • (...) एकल अभिव्यक्ति या कमांड के लिए पर्याप्त है। $(...) (सब- डेप्रिसिएशन ऑपरेटर ) कई अभिव्यक्तियों / आदेशों को संलग्न कर सकता है; ऐसा @() ( सरणी उपसंचालक ऑपरेटर) कर सकता है, और यह अतिरिक्त रूप से सुनिश्चित करता है कि इसका आउटपुट हमेशा एक सरणी के रूप में माना जाता है।

    • विशेष रूप से, उपरोक्त अभिव्यक्तियों को उपरोक्त में से किसी एक में संलग्न किए बिना पहचाना नहीं जाता है:

      • [...] (प्रकार शाब्दिक) और उनके सदस्यों तक पहुंच, जैसे [Environment]::Version
      • .. (रेंज भाव) जैसे 1..10
    • यदि, एक टोकन की शुरुआत में , (...) , $(...) , या @(...) अतिरिक्त वर्णों का अनुसरण करते हैं, तो पहले अतिरिक्त चरित्र को एक नए, अलग तर्क की शुरुआत माना जाता है

    • इसके विपरीत, यदि वे एक निर्विवाद शाब्दिक या केवल-चर संदर्भ से पहले आते हैं, तो $(...) अंदर की तरह काम करता है "..." (एक विस्तार योग्य स्ट्रिंग), (...) एक नया तर्क शुरू करता है जो है एक अभिव्यक्ति, और @(...) को शाब्दिक @ साथ लिया जाता है (...) फिर से एक नया तर्क शुरू होता है जो एक अभिव्यक्ति है।
  • एक @ चर के नाम के बाद (उदाहरण के लिए, @params ) जिसमें पैरामीटर मानों का संग्रह या @params , जो पैरामीटर को अलग करता है।

  • @{ ... } का उपयोग हैशटेबल शाब्दिक पास करने के लिए किया जा सकता है (जैसे, @{ key = 'value' } )।

  • { ... } एक स्क्रिप्ट ब्लॉक ( [scriptblock] स्क्रिप्टब्लॉक [scriptblock] ) बनाता है।

  • स्वयं के द्वारा या टोकन के प्रारंभ में , सदस्य के उपयोग (संपत्ति का उपयोग, विधि कॉल, अनुक्रमण) सहित चर संदर्भों का उपयोग इस प्रकार किया जा सकता है :

    • भाव जैसे $HOME , $PSVersionTable.PSVersion , $someArray[0] , और $someString.ToUpper() को पहचाना जाता है, और उनके अंतर्निहित प्रकार के रूप में लौटाया जाता है।

    • सदस्य अभिगमन के बिना , जैसे कि $HOME रूप में एक साधारण चर संदर्भ के साथ, बाद के वर्ण (संभावित) को उसी तर्क का हिस्सा माना जाता है जिसे तब विस्तार योग्य स्ट्रिंग के रूप में व्याख्या किया जाता है - नीचे देखें।

    • सदस्य अभिगम के साथ , किसी भी अतिरिक्त वर्ण के पहले को एक नए तर्क की शुरुआत माना जाता है (जैसे, $foo.Length-more दो तर्कों में $foo.Length-more परिणाम: $foo.Length और स्ट्रिंग शाब्दिक $foo.Length का मान)।

  • बाकी सब कुछ एक विस्तार योग्य स्ट्रिंग के रूप में माना जाता है , अर्थात, दोहरे-उद्धृत स्ट्रिंग की सामग्री के समान , सिवाय इसके कि मेटाचैटर्स [1] को अभी भी भागने की जरूरत है और कुछ तर्कों को कई तर्कों के रूप में व्याख्या किया गया है

    • एक्सपेंडेबल का अर्थ है कि एम्बेडेड सरल चर संदर्भ (जैसे, $HOME\Desktop या $env:APPDATA\Test ) $env:APPDATA\Test हैं (उनके कड़े मूल्यों के साथ प्रतिस्थापित)।
      ध्यान दें कि यह एक प्रतिनिधित्व में परिणाम कर सकता है जो कंसोल में दिखाए गए मान के डिफ़ॉल्ट आउटपुट प्रारूप से भिन्न होता है, उदाहरण के लिए (फिर से, अधिक जानकारी के लिए यह उत्तर देखें)।

      • यदि आवश्यक हो, तो बाद के वर्णों से इसे अलग करने के लिए {...} में एक चर नाम संलग्न करें (जैसे, ${HOME} )।
    • एक चर मूल्य की संपत्ति तक पहुँचने के लिए या एक सूचकांक का उपयोग करें या एक विधि को कॉल करें या मनमाना आदेशों को एम्बेड करें , आपको $(...) , जैसे, v$($PSVersionTable.PSVersion) में अभिव्यक्ति को संलग्न करना होगा

    • आमतौर पर, "..." में एम्बेडेड चर संदर्भों / अभिव्यक्तियों के साथ टोकन संलग्न करना सबसे सुरक्षित है , क्योंकि यह निम्नलिखित किनारों से बचा जाता है:

      • $(...) एक निर्विवाद टोकन की शुरुआत में एक विस्तार योग्य स्ट्रिंग के हिस्से के रूप में व्याख्या नहीं की जाती है , इसे एक अलग तर्क के रूप में माना जाता है (उदाहरण के लिए, Write-Output $('ab')c दो तर्क में परिणाम: परिणाम $('ab') और शाब्दिक c )।
      • . एक टोकन की शुरुआत में तुरंत एक साधारण चर संदर्भ या सब-डिफरेंशियल के परिणामस्वरूप अलग-अलग तर्क भी मिलते हैं
        (जैसे, .$HOME दो तर्क दिए गए हैं: शाब्दिक; और $HOME का मूल्य)
    • नोट: भले ही विस्तार का परिणाम एक स्ट्रिंग है, यह जरूरी नहीं है कि एक: अंतिम प्रकार को कमांड के पैरामीटर के प्रकार से निर्धारित किया जाता है जिस पर विस्तारित मान बाध्य है।

    • बचना / उद्धृत करना:

      • PowerShell में cmd.exe तुलना में कई अधिक मेटाचैटर हैं, और एक उल्लेखनीय नुकसान यह है कि , एक शाब्दिक उपचार के लिए बच जाना चाहिए , क्योंकि , PowerShell का सरणी-निर्माण ऑपरेटर है।

      • किसी एकल वर्ण से बचने के लिए, इसे ` (बैकटिक) के साथ उपसर्ग करें।

      • मेटाचैकर्स को व्यक्तिगत रूप से भागने की आवश्यकता से बचने के लिए , "..." (दोहरे उद्धरण चिह्नों) या '...' (एकल उद्धरण) में मान संलग्न करें:

        • यदि आप चाहते हैं कि स्ट्रिंग को इंटरपोलेट (विस्तारित) किया जाए , यानी, यदि आप वैरिएबल रेफरेंस और सबएक्सप्रेस को एम्बेड करना चाहते हैं, तो दोहरे उद्धरण चिह्नों का उपयोग करें

          • एक डबल-उद्धृत स्ट्रिंग के अंदर , ` - निम्नलिखित चार -स्केप करें। उन्हें शाब्दिक के रूप में मानने के लिए: ` " $
        • मूल्य को शाब्दिक मानने के लिए एकल उद्धरणों का उपयोग करें

          • एक-उद्धृत स्ट्रिंग के अंदर , एक ' रूप में '' बच
      • सिंगल- या डबल-कोटिंग आमतौर पर एक मूल्य में रिक्त स्थान से बचने का सबसे आसान तरीका है।

  • अंत में, ध्यान दें कि --% , तथाकथित स्टॉप-पार्सिंग सिंबल (PSv3 +), शेष सभी तर्कों की व्याख्या को पूरी तरह से बदल देता है: लीगेसी cmd.exe कमांड लाइनों के साथ उपयोग के लिए डिज़ाइन किया गया, यह सिवाय शेष पंक्ति की व्याख्या करना बंद कर देता है cmd.exe -स्टाइल %...% का विस्तार %...% पर्यावरण चर Get-Help about_Parsing देखें

उद्धृत टोकन का उपयोग करने के लिए:

  • '...' या "..." स्वयं या एक टोकन की शुरुआत में :

    • इन्हें हमेशा की तरह पार्स किया जाता है: एक शाब्दिक ( '...' ) या विस्तार योग्य ( "..." ) स्ट्रिंग के रूप में।
    • किसी भी अतिरिक्त वर्ण के कारण पहला अतिरिक्त वर्ण नए, अलग तर्क की शुरुआत माना जाता है
  • '...' या "..." एक निर्विवाद शाब्दिक या चर-केवल संदर्भ से पहले किया जा रहा है:

    • उन्हें हमेशा की तरह मूल्यांकन किया जाता है और परिणाम (यानी, उद्धरणों को हटा दिया जाता है) के साथ जोड़ा जाता है जो उन्हें (मूल्यांकन) से पहले देता है।

[१] तर्क-विधा रूपक (विशेष वाक्य अर्थ वाले वर्ण) हैं:
<space> ' " ` , ; ( ) { } | & < > @ #
इनमें से, < > @ # केवल एक टोकन की शुरुआत में विशेष हैं।

उदाहरण

Write-Output 1..10    # STRING: -> '1..10'
Write-Output (1..10)  # EXPRESSION: -> @(1, 2, ...)
# Write-Output $(1..10) would work too, but is only necessary if 
# the enclosed expression comprises *multiple* statements.

Write-Output [Environment]::Version  # STRING: -> '[Environment]::Ticks'
Write-Output ([Environment]::Version)  # EXPRESSION: -> a [System.Version] instance.

Write-Output a,b    # !! ARRAY @(1, 2), because "," is not escaped.
Write-Output a`,b   #`# STRING 'ab'                                 
Write-Output "a,b"  # ditto
Write-Output 'a,b'  # ditto

Write-Output $HOME\Desktop   # EXPANDED string (e.g.) 'C:\Users\jdoe\Desktop'
Write-Output "$HOME\Desktop" # ditto
Write-Output '$HOME\Desktop' # LITERAL string '$HOME\Desktop'
Write-Output dir=$HOME       # EXPANDED string (e.g.) 'dir=C:\Users\jdoe\Desktop'

Write-Output $PSVersionTable.PSVersion           # a [System.Version] instance
Write-Output "$($PSVersionTable.PSVersion)/more" # a [string]; e.g., '5.1.14393.576/more'
Write-Output "v$($PSVersionTable.PSVersion)"     # ditto; e.g., 'v5.1.14393.576'

# !!! These DO NOT WORK as intended.
Write-Output $($PSVersionTable.PSVersion)/more # $(...) at the *start*
Write-Output $PSVersionTable.PSVersion/more    # $(...) missing
Write-Output "$PSVersionTable.PSVersion/more"  # $(...) missing
Write-Output .$HOME # Specifically, .$ at the beginning is the problem; escaping . works

मेरे पास निम्नलिखित कोड हैं:

$srv_range = 29..30+40+50..52
$srv_range.GetType()
$NewVMTemplate = New-Object psobject
$NewVMTemplate | Add-Member -MemberType NoteProperty -Name Name -Value $null

$srv_range | % {
    $pod= $_
    $servers = @()
    1..2 | % {
        $server = $NewVMTemplate | Select-Object *
        $server.Name = "pod" + "{0:D2}" -f $pod + "-srv" + $_
        $servers += $server
    }
    ForEach ( $server in $servers) {
        write-host $server.Name
    }
} 

उत्पादन:

PowerCLI C:\ .\eraseme.ps1

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Object[]                                 System.Array
pod29-srv1
pod29-srv2
pod30-srv1
pod30-srv2
pod40-srv1
pod40-srv2
pod50-srv1
pod50-srv2
pod51-srv1
pod51-srv2
pod52-srv1
pod52-srv2

मैं सीएलआई से रेंज इनपुट करना चाहता हूं, लेकिन मुझे इस कोड के साथ निम्न आउटपुट मिलता है

param(

    [Parameter(Mandatory=$False)] $srv_range

)
#$srv_range = 29..30+40+50..52
$srv_range.GetType()
$NewVMTemplate = New-Object psobject
$NewVMTemplate | Add-Member -MemberType NoteProperty -Name Name -Value $null

$srv_range | % {
    $pod= $_
    $servers = @()
    1..2 | % {
        $server = $NewVMTemplate | Select-Object *
        $server.Name = "pod" + "{0:D2}" -f $pod + "-srv" + $_
        $servers += $server
    }
    ForEach ( $server in $servers) {
        write-host $server.Name
    }
} 

PowerCLI C:\ .\eraseme.ps1 29..30+40+50..52

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object
pod29..30+40+50..52-srv1
pod29..30+40+50..52-srv2

मैं सीएलआई से सीमा कैसे इनपुट कर सकता हूं और पहले कोड के समान परिणाम प्राप्त कर सकता हूं?





parameter-passing