आप एक दो-उद्धृत स्ट्रिंग में किसी ऑब्जेक्ट की संपत्ति का उपयोग कैसे कर सकते हैं?


96

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

$DatabaseSettings = @();
$NewDatabaseSetting = "" | select DatabaseName, DataFile, LogFile, LiveBackupPath;
$NewDatabaseSetting.DatabaseName = "LiveEmployees_PD";
$NewDatabaseSetting.DataFile = "LiveEmployees_PD_Data";
$NewDatabaseSetting.LogFile = "LiveEmployees_PD_Log";
$NewDatabaseSetting.LiveBackupPath = '\\LiveServer\LiveEmployeesBackups';
$DatabaseSettings += $NewDatabaseSetting;

जब मैं एक स्ट्रिंग निष्पादित कमांड में गुणों में से एक का उपयोग करने का प्रयास करता हूं:

& "$SQlBackupExePath\SQLBackupC.exe" -I $InstanceName -SQL `
  "RESTORE DATABASE $DatabaseSettings[0].DatabaseName FROM DISK = '$tempPath\$LatestFullBackupFile' WITH NORECOVERY, REPLACE, MOVE '$DataFileName' TO '$DataFilegroupFolder\$DataFileName.mdf', MOVE '$LogFileName' TO '$LogFilegroupFolder\$LogFileName.ldf'"

यह मूल्य के $DatabaseSettingsबजाय केवल मूल्य का उपयोग करने की कोशिश करता है $DatabaseSettings[0].DatabaseName, जो मान्य नहीं है।
मेरा समाधान यह है कि इसे एक नए चर में कॉपी किया जाए।

मैं सीधे दो-उद्धृत स्ट्रिंग में ऑब्जेक्ट की संपत्ति तक कैसे पहुंच सकता हूं?

जवाबों:


163

जब आप एक दोहरे नाम वाले स्ट्रिंग में एक चर नाम संलग्न करते हैं तो इसे उस चर के मान से बदल दिया जाएगा:

$foo = 2
"$foo"

हो जाता है

"2"

यदि आप नहीं चाहते हैं कि आपको सिंगल कोट्स का उपयोग करना है:

$foo = 2
'$foo'

हालाँकि, यदि आप गुणों का उपयोग करना चाहते हैं, या दोहरे-उद्धृत स्ट्रिंग में चर पर अनुक्रमित का उपयोग करना चाहते हैं, तो आपको उस सब-एफ़एक्सप्रेशन को संलग्न करना होगा $():

$foo = 1,2,3
"$foo[1]"     # yields "1 2 3[1]"
"$($foo[1])"  # yields "2"

$bar = "abc"
"$bar.Length"    # yields "abc.Length"
"$($bar.Length)" # yields "3"

PowerShell केवल उन मामलों में चर का विस्तार करता है, अधिक कुछ नहीं। इंडेक्स, गुण या पूर्ण गणना सहित अधिक जटिल अभिव्यक्तियों के मूल्यांकन को बाध्य करने के लिए, आपको उन सबप्रेशन ऑपरेटर में संलग्न करना होगा $( )जो अंदर अभिव्यक्ति का मूल्यांकन करते हैं और स्ट्रिंग में एम्बेडेड होते हैं।


यह काम करता है, लेकिन मुझे आश्चर्य होता है कि अगर मैं पहले से ही
समझ

2
@ ozzy432836 आप निश्चित रूप से कर सकते हैं। या प्रारूप स्ट्रिंग्स का उपयोग करें। यह आमतौर पर वास्तव में मायने नहीं रखता है और व्यक्तिगत पसंद के लिए नीचे आता है।
जॉय

15

@ जॉय के पास सही उत्तर है, लेकिन सिर्फ इसलिए थोड़ा और जोड़ना है कि आपको मूल्यांकन को मजबूर करने की आवश्यकता क्यों है $():

आपके उदाहरण कोड में एक अस्पष्टता होती है जो इंगित करती है कि क्यों PowerShell के निर्माताओं ने विस्तार को केवल सीमित चर संदर्भों तक सीमित किया है और गुणों तक पहुंच का समर्थन नहीं किया है (एक तरफ के रूप में: स्ट्रिंग विस्तार ToString()ऑब्जेक्ट पर विधि को कॉल करके किया जाता है , जो कुछ "विषम" परिणामों की व्याख्या कर सकते हैं)।

आपका उदाहरण कमांड लाइन के बहुत अंत में निहित है:

...\$LogFileName.ldf

यदि डिफ़ॉल्ट रूप से ऑब्जेक्ट्स के गुणों का विस्तार किया गया था, तो ऊपर का समाधान होगा

...\

चूँकि संदर्भित की गई वस्तु $LogFileNameमें कोई संपत्ति नहीं होगी ldf, जिसे $null(या एक रिक्त स्ट्रिंग) चर के लिए प्रतिस्थापित किया जाएगा।


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

धन्यवाद दोस्तों! जोहानस आपको लगता है कि एक स्ट्रिंग में गुणों तक पहुंच खराब क्यों है? यह कैसे किया जाएगा सुझाव है?
caveman_dick

caveman: यह सिर्फ एक चीज थी जिसने मेरी आंख को एक संभावित त्रुटि कारण के रूप में पकड़ा। आप निश्चित रूप से कर सकते हैं और यह कुछ भी अजीब नहीं है, लेकिन $ () ऑपरेटर को छोड़ने पर यह "विफल" चिल्लाता है क्योंकि यह काम नहीं कर सकता है। इस प्रकार मेरा जवाब सिर्फ एक शिक्षित अनुमान था कि आपके संभावित कारण क्या हो सकते हैं, पहले संभावित असफलता के कारण मैं देख सकता था। क्षमा करें यदि यह ऐसा लगता है, लेकिन यह टिप्पणी किसी भी सर्वोत्तम अभ्यास का उल्लेख नहीं कर रही थी।
जॉय

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

9

@ जोय का अच्छा जवाब है। String.Format समतुल्य के साथ अधिक .NET लुक के साथ एक और तरीका है, मैं इसे पसंद करता हूं जब वस्तुओं पर गुणों तक पहुंच होती है:

कार के बारे में बातें:

$properties = @{ 'color'='red'; 'type'='sedan'; 'package'='fully loaded'; }

एक वस्तु बनाएँ:

$car = New-Object -typename psobject -Property $properties

एक स्ट्रिंग प्रक्षेपित करें:

"The {0} car is a nice {1} that is {2}" -f $car.color, $car.type, $car.package

आउटपुट:

# The red car is a nice sedan that is fully loaded

हाँ, जो अधिक पठनीय है, खासकर यदि आप .net कोड के अभ्यस्त हैं धन्यवाद! :)
caveman_dick

3
जब आप पहली बार प्रारूप स्ट्रिंग्स का उपयोग करते हैं, तो यह देखने के लिए एक गोच है, जो कि आपको अक्सर परेंस में अभिव्यक्ति को संलग्न करने की आवश्यकता होगी। आप उदाहरण के लिए, केवल इसलिए नहीं लिख सकते write-host "foo = {0}" -f $fooक्योंकि PowerShell के -fलिए ForegroundColorपैरामीटर के रूप में माना जाएगा write-host। इस उदाहरण में आपको इसकी आवश्यकता होगी write-host ( "foo = {0}" -f $foo )। यह मानक पावरशेल व्यवहार है, लेकिन ध्यान देने योग्य है।
andyb

बस पांडित्यपूर्ण होने के लिए, ऊपर का उदाहरण "स्ट्रिंग प्रक्षेप" नहीं है, यह "समग्र स्वरूपण" है। चूँकि Powershell inextricably .NET के लिए बाध्य है जिसके लिए C # और VB.NET प्राथमिक प्रोग्रामिंग भाषाएं हैं, "स्ट्रिंग इंटरपोलेशन" और "इंटरपोलेटेड स्ट्रिंग" (और कुछ भी समान) शब्द केवल उन नए $ प्रीपिंग स्ट्रिंग्स पर लागू होने चाहिए जो उन में पाए जाते हैं भाषाएँ (C # 6 और VB.NET 14)। इन स्ट्रिंग्स में, पैरामीटर एक्सप्रेशंस को सीधे न्यूमेरिकल पैरामीटर रेफरेंस के बजाय स्ट्रिंग में एंबेड किया जाता है, वास्तविक एक्सप्रेशंस के साथ तब आर्ग्युमेंट किया जाता है String.Format
उबेर क्लुगर

@andyb, प्रारूप स्ट्रिंग "गोचैस" के बारे में। यह वास्तव में अभिव्यक्ति और तर्क मोड के बीच का अंतर है ( देखें_पर्सिंग )। कमानों को टोकन (एक सार्थक स्ट्रिंग बनाने वाले पात्रों के समूह) में पार्स किया जाता है । अंतरिक्ष टोकन को अलग कर देता है जो विलय कर देगा लेकिन अन्यथा अनदेखा किया जाता है। यदि कमांड का पहला टोकन एक संख्या, चर, स्टेटमेंट कीवर्ड (यदि, जबकि, आदि), अपर ऑपरेटर, {, आदि ... है तो पार्सिंग मोड Expressionअन्यथा Argument(कमांड टर्मिनेटर तक) है।
उबर क्लूगर

8

दस्तावेज़ नोट: Get-Help about_Quoting_Rulesस्ट्रिंग प्रक्षेप को कवर करता है, लेकिन, PSv5 के रूप में, गहराई में नहीं।

की मदद के लिए जोई की मददगार जवाब एक साथ व्यावहारिक सारांश PowerShell का स्ट्रिंग विस्तार (में स्ट्रिंग प्रक्षेप डबल-कोटेड तार ( "..."), डबल-कोटेड सहित यहां-तार ):

  • केवल संदर्भ जैसे कि $foo, $global:foo(या $script:foo, ...) और$env:PATH (पर्यावरण चर) को तब पहचाना जाता है जब सीधे"..." तार में पिरोया जाता है - अर्थात, केवल चर संदर्भ ही विस्तारित होता है, चाहे जो भी हो।

    • करने के लिए एक चर नाम को स्पष्ट स्ट्रिंग में बाद में पात्रों से, में यह जोड़ देना {और} ; जैसे, ${foo}
      यह अगर चर नाम एक के बाद आता है विशेष रूप से महत्वपूर्ण है :, के रूप में PowerShell अन्यथा के बीच सब कुछ पर विचार करेंगे $और :एक दायरे में आम तौर पर करने के लिए प्रक्षेप के कारण विनिर्देशक है, असफल ; उदाहरण के लिए, "$HOME: where the heart is."टूट जाता है, लेकिन "${HOME}: where the heart is."काम करता है।
      (वैकल्पिक रूप से, `-स्केप :: द "$HOME`: where the heart is.")।

    • एक $या एक शाब्दिक के" रूप में इलाज करने के लिए , इसे एस्केप चार के साथ उपसर्ग करें (एक बैकटिक ); उदाहरण के लिए:`
      "`$HOME's value: `"$HOME`""

  • सरणी सब्सक्राइबर्स का उपयोग करने और ऑब्जेक्ट वैरिएबल के गुणों तक पहुंचने सहित किसी अन्य चीज के लिए , आपको सब- इंप्रेशन ऑपरेटर (जैसे, या ) में अभिव्यक्ति संलग्न$(...) करना होगा।"PS version: $($PSVersionTable.PSVersion)""1st el.: $($someArray[0])"

    • $(...)यहां तक ​​कि उपयोग करने से आप पूरे कमांड लाइनों से आउटपुट को दोहरे-उद्धृत स्ट्रिंग्स (जैसे, "Today is $((Get-Date).ToString('d')).") में एम्बेड कर सकते हैं ।
  • इंटरपोलेशन परिणाम आवश्यक रूप से डिफ़ॉल्ट आउटपुट प्रारूप के समान नहीं दिखते हैं (आप जो देखते हैं यदि आप चर / उपप्रकार को सीधे कंसोल पर प्रिंट करते हैं, उदाहरण के लिए, जिसमें डिफ़ॉल्ट फॉर्मेटर शामिल है; देखें Get-Help about_format.ps1xml):

    • संग्रह , सरणियों सहित, तत्वों के स्ट्रिंग निरूपण के बीच एक ही स्थान रखकर स्ट्रिंग में परिवर्तित हो जाते हैं (डिफ़ॉल्ट रूप से, एक अलग विभाजक सेटिंग द्वारा निर्दिष्ट किया जा सकता है $OFS), जैसे, "array: $(@(1, 2, 3))"पैदावारarray: 1 2 3

    • किसी भी अन्य प्रकार के उदाहरण (संग्रह के तत्वों सहित, जो स्वयं संग्रह नहीं हैं) को अपरिवर्तनीय संस्कृति के साथ विधि कहकर या तो कठोर किया जाता है , यदि उदाहरण का प्रकार इंटरफ़ेस [1] का समर्थन करता है , या कॉल करके , जो ज्यादातर मामलों में बस चालान करता है अंतर्निहित .NET प्रकार की विधि IFormattable.ToString()IFormattable.psobject.ToString().ToString()[2] , जो एक सार्थक प्रतिनिधित्व दे सकती है या नहीं भी दे सकती है: जब तक कि (गैर-आदिम) प्रकार ने विशेष रूप से .ToString()विधि को ओवरराइड नहीं किया है, आपको मिलेगा सभी प्रकार पूर्ण नाम (जैसे, "hashtable: $(@{ key = 'value' })"पैदावार hashtable: System.Collections.Hashtable) है।

    • करने के लिए कंसोल में के रूप में ही उत्पादन प्राप्त , एक उपसूचक और प्रयोग करने के लिए पाइपOut-String और लागू .Trim(), किसी भी प्रमुख और अनुगामी खाली लाइनों को हटाने के लिए अगर वांछित; जैसे,
      "hashtable:`n$((@{ key = 'value' } | Out-String).Trim())"पैदावार:

      hashtable:                                                                                                                                                                          
      Name                           Value                                                                                                                                               
      ----                           -----                                                                                                                                               
      key                            value      

[1] यह शायद आश्चर्य की बात व्यवहार का मतलब है कि, प्रकार के लिए कि समर्थन संस्कृति के प्रति संवेदनशील अभ्यावेदन, $obj.ToString()एक पैदावार वर्तमान -culture-उचित प्रतिनिधित्व, जबकि "$obj"(स्ट्रिंग प्रक्षेप) हमेशा एक में परिणाम संस्कृति-अपरिवर्तनीय प्रतिनिधित्व - देखना यह उत्तर मेरा।

[२] उल्लेखनीय ओवरराइड्स:
* संग्रह की पहले से चर्चा की गई कड़ी (कुछ की बजाय तत्वों की अंतरिक्ष से अलग सूची System.Object[])।
* Hashtable- तरह के प्रतिनिधित्व [pscustomobject]उदाहरणों (समझाया यहाँ ) के बजाय रिक्त स्ट्रिंग

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