{"id":9611,"date":"2012-04-28T00:01:00","date_gmt":"2012-04-28T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2012\/04\/28\/weekend-scripter-learn-how-to-handle-string-output-from-within-powershell\/"},"modified":"2012-04-28T00:01:00","modified_gmt":"2012-04-28T00:01:00","slug":"weekend-scripter-learn-how-to-handle-string-output-from-within-powershell","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/weekend-scripter-learn-how-to-handle-string-output-from-within-powershell\/","title":{"rendered":"Weekend Scripter: Learn How to Handle String Output from Within PowerShell"},"content":{"rendered":"<p><b>Summary<\/b>: Microsoft Scripting Guy, Ed Wilson, discusses several different ways to handle string output from inside Windows PowerShell.<\/p>\n<p>Microsoft Scripting Guy, Ed Wilson, is here. It is official&mdash;the 2012 Scripting Games are finally over (actually they were over yesterday, and I promised not to say any more about the games). Today the Scripting Wife and I are heading to Virginia Beach where I will speak at the <a href=\"http:\/\/minasiconference.wordpress.com\/minasi-2012-timetable\/\" target=\"_blank\">Mark Minasi Conference<\/a>. If you happen to be in the area, stop by and check it out. It will be a great conference, and I am really looking forward to it.<\/p>\n<p>One of the things that beginners have a problem with is formatting output. In particular forming strings that contain data. One of the things Windows PowerShell does really well is handle input and output seamlessly. For example, many cmdlets automatically emit data. For example, the <b>Get-Process<\/b> cmdlet returns a nicely formatted table as shown here.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/1300.Wes-4-28-12-1.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/1300.Wes-4-28-12-1.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>But things begin to go downhill really fast. Suppose you have a process named <i>Notepad <\/i>and you want to display the name and the process ID (PID). One way to approach this task is to use the <b>Get-Process <\/b>cmdlet to retrieve the instance of the <i>Notepad <\/i>process with which you are interested in working. Next you could store this process object into a variable, and then use expanding quotation marks (double quotation marks as opposed to literal quotation marks, which are single quotation marks) to expand the <b>Name<\/b> and <b>ID<\/b> properties. This technique is shown here.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; notepad<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $n = Get-Process notepad<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; &#8220;the name is $n.Name and the PID is $n.Id&#8221;<\/p>\n<p>The problem is that when the string displays to the Windows PowerShell console, the object <i>unravels <\/i>and you do not get the property value that you might have been expecting to obtain. Instead, you get a jumble of letters that do not seem to make any sense. These commands and their associated output are shown here.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/5270.wes-4-28-12-2.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/5270.wes-4-28-12-2.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>There are several ways to suppress the unraveling of the objects. One way is to use a subexpression. A subexpression is comprised of a dollar sign, and a pair of parentheses. The subexpression forces the evaluation of the object\/property value and then returns the value of the property back to the string for display. A pair of parentheses causes Windows PowerShell to evaluate an expression prior to displaying the output. Therefore, it can display the contents of things like variables. A subexpression takes this a step further and causes the evaluation of the value of a property from an object. The syntax of this is shown here.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; notepad<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $n = Get-Process notepad<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; &#8220;the name is $($n.Name) and the PID is $($n.Id)&#8221;<\/p>\n<p style=\"padding-left: 30px\">the name is notepad and the PID is 2816<\/p>\n<p>The command to start notepad, retrieve an instance of the object and store it in the <b>$n<\/b> variable, and display the property values is shown here with the associated output.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/7140.wes-4-28-12-3.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/7140.wes-4-28-12-3.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>Another approach to this problem is to use concatenation. The concatenation operator is the plus sign (+). Concatenation glues the output together so it will display on the same line. By using concatenation, you place your string values inside quotation marks. You then close the quotation marks and call the object\/property to display it. You then open another pair of quotation marks to add your additional string data. You continue with this pattern until you have completed displaying your data.<\/p>\n<p>This approach to merging data from property values and strings is essentially unchanged from the earliest VBScript days. The big trick with this technique is that you must remember to include spacing between the string and the property value. If you do not, the concatenation operator will glue your string together. This approach is shown here.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; notepad<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $n = Get-Process notepad<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; &#8220;the name is &#8221; + $n.name + &#8221; and the PID is &#8221; + $n.id<\/p>\n<p>The commands and the output associated with the commands are shown here.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/1768.wes-4-28-12-4.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/1768.wes-4-28-12-4.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>A different problem exists when working with multiple objects. In this situation, the properties appear to disappear. This is because the process objects (in this example) hide inside an array and when attempting to access directly the property values. You must first deal with the array, and then you can work with the property values. If you do not first deal with the array, when you attempt to display the property values, nothing appears in the output. This situation is shown in the image here.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/5661.wes-4-28-12-5.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/5661.wes-4-28-12-5.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>Because there are multiple objects in the array, it is necessary to walk through the array so that the individual values from the properties of the individual objects are accessible. The easiest way to accomplish this is to pipe the array of objects to the <b>Foreach-Object<\/b> cmdlet. In the script block portion of the <b>Foreach-Object<\/b> cmdlet, add the code from the previous examples. This technique is shown here (this example uses the % symbol, which is an alias for the <b>Foreach-Object<\/b> cmdlet).<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; 1..3 | % {notepad}<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $n = Get-Process notepad<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $n | % {&#8220;the name is &#8221; + $_.name + &#8221; and the PID is &#8221; + $_.id}<\/p>\n<p>The code, from this technique, along with the associated output appears here.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2046.wes-4-28-12-6.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/2046.wes-4-28-12-6.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>You can use a similar technique to using the <b>Foreach-Object <\/b>cmdlet by using the <i>ForEach <\/i>language statement to walk through the array and display the property values. The <i>ForEach <\/i>language statement is a bit more complex to use than the <b>Foreach-Object <\/b>cmdlet, but it has the advantage of being a bit easier to read, and of being generally faster due to not involving the overhead of the pipeline. The use of the <i>ForEach <\/i>language statement to walk through the array is shown here.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; 1..3 | % {start-process notepad -WindowStyle minimized}<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $n = Get-Process notepad<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; foreach($a in $n) {&#8220;the name is &#8221; + $a.name + &#8221; and the PID is &#8221; + $a.id}<\/p>\n<p>Because an array contains the objects, it is possible to index the array to display the property values. One easy way to do this is to use the same type of range operator that created the three instances of <i>Notepad<\/i> in the first place. When it is created, the <b>$n<\/b> variable stores the objects that are returned by the <b>Get-Process <\/b>cmdlet. The range operator passes the numbers that become the index indicators to select the specific element from the array. The dotted notation selects the applicable properties from the process object. This technique is shown here.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; 0..2 | % {start-process notepad -WindowStyle minimized}<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $n = Get-Process notepad<\/p>\n<p style=\"padding-left: 30px\">0..2 | % {&#8220;the name is &#8221; + $n[$_].name + &#8221; and the PID is &#8221; + $n[$_].id}<\/p>\n<p>Rather than using concatenation or a subexpression to display the values from the object\/property, a cleaner (and therefore, more reliable) method uses parameter substitution and the format operator. At first glance, this technique appears strange&mdash;although not necessarily any stranger than indexing into the array to retrieve the property values. When you become familiar with this technique, you may find that you like it better than using concatenation or a subexpression. The basic pattern is shown here.<\/p>\n<table border=\"1\" cellspacing=\"0\" cellpadding=\"0\">\n<tbody>\n<tr>\n<td width=\"128\" valign=\"top\">\n<p>Opening quotation mark<\/p>\n<\/td>\n<td width=\"128\" valign=\"top\">\n<p>Parameter to replace<\/p>\n<\/td>\n<td width=\"128\" valign=\"top\">\n<p>Format operator<\/p>\n<\/td>\n<td width=\"128\" valign=\"top\">\n<p>Value to substitute for first parameter<\/p>\n<\/td>\n<td width=\"128\" valign=\"top\">\n<p>Closing quotation mark<\/p>\n<\/td>\n<\/tr>\n<tr>\n<td width=\"128\" valign=\"top\">\n<p>&nbsp; &nbsp; &nbsp;&ldquo;<\/p>\n<\/td>\n<td width=\"128\" valign=\"top\">\n<p>&nbsp; &nbsp; &nbsp;{0}<\/p>\n<\/td>\n<td width=\"128\" valign=\"top\">\n<p>&nbsp; &nbsp; &nbsp;-f<\/p>\n<\/td>\n<td width=\"128\" valign=\"top\">\n<p>&nbsp; &nbsp; &nbsp;zero<\/p>\n<\/td>\n<td width=\"128\" valign=\"top\">\n<p>&nbsp; &nbsp; <span>&rdquo;<\/span><\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>This pattern with the associated output is shown in the following example.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; &#8220;The first number {0} marks the first pattern&#8221; -f &#8220;zero&#8221;<\/p>\n<p style=\"padding-left: 30px\">The first number zero marks the first pattern<\/p>\n<p>The advantage of using parameter substitution is that it is easier to format the output exactly as required. Going back to the example of indexing into the array, parameter substitution replaces the concatenation previously used. The revised example is shown here.<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; 0..2 | % {start-process notepad -WindowStyle minimized}<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; $n = Get-Process notepad<\/p>\n<p style=\"padding-left: 30px\">PS C:\\&gt; 0..2 | % {&#8220;The name is {0} and the PID is {1}&#8221; -f $n[$_].name, $n[$_].id}<\/p>\n<p>The following output illustrates the use of parameter substitution to retrieve the property values from the array and to format the output.<\/p>\n<p><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/3835.wes-4-28-12-7.png\"><img decoding=\"async\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/3835.wes-4-28-12-7.png\" alt=\"Image of command output\" title=\"Image of command output\" \/><\/a><\/p>\n<p>Well, that is enough for now about formatting output. Join me tomorrow when I will continue the discussion by examining the use of various cmdlets.<\/p>\n<p>I invite you to follow me on <a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\">Twitter<\/a> and <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\" target=\"_blank\">Facebook<\/a>. If you have any questions, send email to me at <a href=\"mailto:scripter@microsoft.com\" target=\"_blank\">scripter@microsoft.com<\/a>, or post your questions on the <a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<p><b>Ed Wilson, Microsoft Scripting Guy<\/b>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Microsoft Scripting Guy, Ed Wilson, discusses several different ways to handle string output from inside Windows PowerShell. Microsoft Scripting Guy, Ed Wilson, is here. It is official&mdash;the 2012 Scripting Games are finally over (actually they were over yesterday, and I promised not to say any more about the games). Today the Scripting Wife and [&hellip;]<\/p>\n","protected":false},"author":596,"featured_media":87096,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[51,3,4,336,61,45],"class_list":["post-9611","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-getting-started","tag-scripting-guy","tag-scripting-techniques","tag-strings","tag-weekend-scripter","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Microsoft Scripting Guy, Ed Wilson, discusses several different ways to handle string output from inside Windows PowerShell. Microsoft Scripting Guy, Ed Wilson, is here. It is official&mdash;the 2012 Scripting Games are finally over (actually they were over yesterday, and I promised not to say any more about the games). Today the Scripting Wife and [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/9611","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/users\/596"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=9611"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/9611\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media\/87096"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/media?parent=9611"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=9611"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=9611"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}