{"id":16691,"date":"2010-10-27T00:01:00","date_gmt":"2010-10-27T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2010\/10\/27\/use-net-framework-classes-to-work-with-strings-in-windows-powershell\/"},"modified":"2010-10-27T00:01:00","modified_gmt":"2010-10-27T00:01:00","slug":"use-net-framework-classes-to-work-with-strings-in-windows-powershell","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/use-net-framework-classes-to-work-with-strings-in-windows-powershell\/","title":{"rendered":"Use .NET Framework Classes to Work with Strings in Windows PowerShell"},"content":{"rendered":"<p>&nbsp;<\/p>\n<p><b>Summary:<\/b> Learn how to use .NET Framework classes to work with strings in Windows PowerShell in this Scripting Guys how-to post.<\/p>\n<p>&nbsp;<\/p>\n<p><img decoding=\"async\" height=\"34\" width=\"34\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" align=\"left\" alt=\"Hey, Scripting Guy! Question\" border=\"0\" title=\"Hey, Scripting Guy! Question\" \/>Hey, Scripting Guy! I have been writing VBScript code for years. One thing I really liked about VBScript was the large number of functions that manipulated strings. I know Microsoft seems to love XML, but there is a lot of overhead associated with XML, and very often, I need to parse and manipulate strings. When I look at the Windows PowerShell cmdlets, I do not see very many cmdlets that would allow me to manipulate text. <\/p>\n<p>&#8212; BW<\/p>\n<p>&nbsp;<\/p>\n<p><img decoding=\"async\" height=\"34\" width=\"34\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" align=\"left\" alt=\"Hey, Scripting Guy! Answer\" border=\"0\" title=\"Hey, Scripting Guy! Answer\" \/>Hello BW, Microsoft Scripting Guy Ed Wilson here. When I was a student at the university, I majored in music for a while. One of my favorite classes was a music theory class that focused on string instruments. It was a string theory class. Today, I will examine string theory as it applies to Windows PowerShell. In continuing my discussion of the .NET Framework as it applies to Windows PowerShell, I will examine the <b>System.String<\/b> .NET Framework class. <\/p>\n<p>Strings are letters, words, and numbers that function like letters and words. The <b>GetType<\/b> method can be used to determine what kind of object one is working with. This is shown here.<\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; (&#8220;this is a string&#8221;).GetType()<\/p>\n<p>IsPublic IsSerial Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; BaseType<br \/>&#8212;&#8212;&#8211; &#8212;&#8212;&#8211; &#8212;-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8212;&#8212;&#8211;<br \/>True&nbsp;&nbsp;&nbsp;&nbsp; True&nbsp;&nbsp;&nbsp;&nbsp; String&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; System.Object<\/p>\n<p>PS C:\\&gt;<\/span><\/p>\n<p>As seen above, &#8220;this is a string&#8221; is an instance of a string object. The .NET Framework class string, is located in the <b>System<\/b> .NET Framework namespace. Therefore, I will frequently refer it to it as the <b>System.String<\/b> class because it helps me remember where in the labyrinthine .NET Framework hierarchy the <b>String<\/b> class resides. Knowing where the class resides is useful when I have to look up information on MSDN, but to create some classes I have to specify both the namespace and the class name. <\/p>\n<p>If the string &#8220;this is a string&#8221; is an instance of the <b>System.String<\/b> class, what does that really mean? It means that the class contains methods and properties. The methods do things and are like verbs, whereas the properties describe things and are like adjectives. To find the members (methods and properties) of the <b>System.String<\/b> class, I can use the <b>Get-Member<\/b> Windows PowerShell cmdlet. To do this, I first open Windows PowerShell by clicking <b>Start<\/b> \\ <b>Programs<\/b> \\ <b>Accessories<\/b> \\ <b>Windows PowerShell<\/b> \\ <b>Windows PowerShell<\/b>. If you are tired of meandering through five levels of nested menus to start Windows PowerShell, you may want to create a desktop shortcut to Windows PowerShell. <a href=\"http:\/\/blogs.technet.com\/b\/heyscriptingguy\/archive\/2010\/03\/28\/hey-scripting-guy-march-28-2010.aspx\">The Scripting Wife<\/a> talks about this technique. The technique of piping a string to the <b>Get-Member<\/b> cmdlet is illustrated here. The <span style=\"font-family: courier new,courier\">PS C:\\&gt;<\/span> is not part of the command, but is the Windows PowerShell prompt. <\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; &#8220;this is a string&#8221; | Get-Member<\/span><\/p>\n<p>After the command is typed, and the enter key pressed to submit the command to Windows PowerShell for interpretation, the output seen in the following figure appears. <\/p>\n<p><img decoding=\"async\" src=\"https:\/\/msdnshared.blob.core.windows.net\/media\/TNBlogsFS\/prod.evol.blogs.technet.com\/CommunityServer.Blogs.Components.WeblogFiles\/00\/00\/00\/76\/18\/6114.HSG-10-27-10-01.JPG\" border=\"0\" \/><\/p>\n<p>&nbsp;<\/p>\n<p>There are many ways to call a method on an instance of a class such as the <b>System.String<\/b> class seen here. In every example, a dotted notation is used immediately after the class instance that is followed by the method name. Several different ways of calling the toupper method are illustrated here. <\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; (&#8220;this is A string&#8221;).toupper()<br \/>THIS IS A STRING<br \/>PS C:\\&gt; &#8220;this is A string&#8221;.toupper()<br \/>THIS IS A STRING<br \/>PS C:\\&gt; $a = &#8220;this is A string&#8221;<br \/>PS C:\\&gt; $a.ToUpper()<br \/>THIS IS A STRING<br \/>PS C:\\&gt; $b = New-Object system.string(&#8220;this is A string&#8221;)<br \/>PS C:\\&gt; $b.ToUpper()<br \/>THIS IS A STRING<br \/>PS C:\\&gt; [string]&#8221;this is A string&#8221;.toupper()<br \/>THIS IS A STRING<br \/>PS C:\\&gt; ([string]&#8221;this is A string&#8221;).toupper()<br \/>THIS IS A STRING<br \/>PS C:\\&gt; [string](&#8220;this is A string&#8221;).toupper()<br \/>THIS IS A STRING<br \/>PS C:\\&gt;<\/span><\/p>\n<p>The <b>tolower<\/b> method works exactly like the <b>toupper<\/b> method. Whereas the <b>toupper<\/b> method will take a string and convert all the letters in the string to uppercase (hence the name <b>toupper<\/b>) the <b>tolower<\/b> method performs the opposite action. It converts a string to all lowercase characters. In the following example a mixed case string is converted to all uppercase letters and stored in the <i>$a<\/i> variable. The contents of the <i>$a<\/i> variable are then displayed on the Windows PowerShell console line. The <b>tolower<\/b> method is then called to convert the uppercase letters stored in the <em>$a<\/em> variable to lowercase. The output of the <b>tolower<\/b> method call is not stored (that is the results are not stored in a variable, they are only displayed on the Windows PowerShell console line). The commands and their associated output are shown here.&nbsp; <\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; $a = [string](&#8220;this is A string&#8221;).toupper()<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; $a<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">THIS IS A STRING<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; $a.ToLower()<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">this is a string<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt;<\/span><\/p>\n<p>The <b>toupper<\/b> or the <b>tolower<\/b> methods are useful for evaluating user input. In the example that follows, the <b>Read-Host<\/b> Windows PowerShell cmdlet asks for input from the user. If the user types <i>yes<\/i>, the code continues. Refer to this code for the details. <\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; $rtn = Read-Host &#8220;Do you wish to continue? yes \/ no&#8221;<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">Do you wish to continue? yes \/ no: yes<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; if($rtn.ToUpper() -eq &#8220;YES&#8221;) {&#8220;continue&#8221;} ELSE { &#8220;don&#8217;t continue&#8221; }<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">continue<\/span><\/p>\n<p>If the user can be counted upon to type exactly what the prompt expects, then everything will work perfectly. However, this is an unlikely expectation. In the example that follows, the same prompt is displayed by using the <b>Read-Host<\/b> cmdlet. Instead of typing <i>yes<\/i> the user types <i>Yes, I would like to continue<\/i> and the <b>$rtn.ToUpper<\/b> code fails. The <b>contains<\/b> method returns a Boolean value if a match in a string is detected. Unfortunately, it is case-sensitive, and because the user typed <i>Yes<\/i> instead of <i>yes,<\/i> the <b>contains<\/b> method fails also. What is needed is the ability to combine the <b>tolower<\/b> method and the <b>contains<\/b> method. The last line of the following code achieves that. <\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; $rtn = Read-Host &#8220;Do you wish to continue? yes \/ no&#8221;<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">Do you wish to continue? yes \/ no: Yes&nbsp; I would like to continue.<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; if($rtn.ToUpper() -eq &#8220;yes&#8221;) { &#8220;continue&#8221; } ELSE { &#8220;don&#8217;t continue&#8221; }<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">don&#8217;t continue<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; if($rtn.contains(&#8220;yes&#8221;)) { &#8220;continue&#8221; } ELSE { &#8220;don&#8217;t continue&#8221; }<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">don&#8217;t continue<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; if($rtn.tolower().contains(&#8220;yes&#8221;)) { &#8220;continue&#8221; } ELSE { &#8220;don&#8217;t continue&#8221; }<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">continue<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt;<\/span><\/p>\n<p>A common problem arising from working with strings is additional spaces. This can cause problems with reporting if the information writes to a database because it can cause equivalent records to report as separate entries. Additional spaces can also cause matches to fail. Luckily, several methods from the <b>System.String<\/b> .NET Framework class resolve the problem of additional spaces. The methods are <b>TrimStart<\/b>, <b>TrimEnd<\/b>, and <b>Trim<\/b>. I will examine using the <b>TrimStart<\/b> method first. In the example that follows, a string that contains both leading and trailing spaces is assigned to the <i>$a<\/i> variable. The <b>TrimStart<\/b> method is used to remove leading spaces and the result is stored in the <i>$b<\/i> variable. To show where spaces remain, the <b>Replace<\/b> method replaces spaces with a period. This shows in the following output. <\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; $a = &#8221; this is a string&nbsp; &#8220;<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; $b = $a.TrimStart()<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; $b.Replace(&#8221; &#8220;,&#8221;.&#8221;)<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">this.is.a.string..<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt;<\/span><\/p>\n<p>The <b>TrimEnd<\/b> method works just as the <b>TrimStart<\/b> method does, except that it removes spaces from the end of a string. The string with spaces is assigned to the <i>$a<\/i> variable. The <b>TrimEnd<\/b> method removes spaces from the end of the string and assigns the result to the <i>$b<\/i> variable. Finally, the <b>Replace<\/b> method replaces spaces with periods&nbsp; so that the spaces are more clearly visualized. The output that follows shows this procedure. <\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; $a = &#8221; this is a string&nbsp; &#8220;<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; $b = $a.TrimEnd()<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; $b.Replace(&#8221; &#8220;,&#8221;.&#8221;)<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">.this.is.a.string<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt;<\/span><\/p>\n<p>The last trim method I want to discuss is the one that I use most frequently. It is the <b>Trim<\/b> method. What I like about the <b>Trim<\/b> method is that it removes leading spaces in addition to trailing spaces. To achieve the same effect, if one did not know about the <b>Trim<\/b> method, would involve calling both the <b>TrimStart<\/b> and the <b>TrimEnd<\/b> methods as shown here. <\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; $a = &#8221; this is a string&nbsp; &#8220;<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; $b = $a.TrimEnd().TrimStart()<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; $b.Replace(&#8221; &#8220;,&#8221;.&#8221;)<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">this.is.a.string<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt;<\/span><\/p>\n<p>In fact, the <b>Trim<\/b> method does the same. It removes leading spaces just as the <b>TrimStart<\/b> method does, and it removes trailing spaces as the <b>TrimEnd<\/b> method does. The following code shows this concept. <\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; $a = &#8221; this is a string&nbsp; &#8220;<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; $b = $a.Trim()<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt; $b.Replace(&#8221; &#8220;,&#8221;.&#8221;)<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">this.is.a.string<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: courier new,courier\">PS C:\\&gt;<\/span><\/p>\n<p>BW, that is all there is to using .NET Framework classes to work with strings. My review of the .NET Framework for Windows PowerShell week will continue tomorrow when I will talk about more how to work with the .NET Framework classes. <\/p>\n<p>I invite you to follow me on <a target=\"_blank\" href=\"http:\/\/bit.ly\/scriptingguystwitter\">Twitter<\/a> or <a href=\"http:\/\/bit.ly\/scriptingguysfacebook\">Facebook<\/a>. If you have any questions, send email to me at <a target=\"_blank\" href=\"mailto:scripter@microsoft.com\">scripter@microsoft.com<\/a> or post them on the <a target=\"_blank\" href=\"http:\/\/bit.ly\/scriptingforum\">Official Scripting Guys Forum<\/a>. See you tomorrow. Until then, peace.<\/p>\n<p>&nbsp;<\/p>\n<p><b>Ed Wilson, Microsoft Scripting Guy<\/b><\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; Summary: Learn how to use .NET Framework classes to work with strings in Windows PowerShell in this Scripting Guys how-to post. &nbsp; Hey, Scripting Guy! I have been writing VBScript code for years. One thing I really liked about VBScript was the large number of functions that manipulated strings. I know Microsoft seems to [&hellip;]<\/p>\n","protected":false},"author":595,"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,21,45],"class_list":["post-16691","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-getting-started","tag-scripting-guy","tag-scripting-techniques","tag-string-manipulation","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>&nbsp; Summary: Learn how to use .NET Framework classes to work with strings in Windows PowerShell in this Scripting Guys how-to post. &nbsp; Hey, Scripting Guy! I have been writing VBScript code for years. One thing I really liked about VBScript was the large number of functions that manipulated strings. I know Microsoft seems to [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/16691","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\/595"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/comments?post=16691"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/16691\/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=16691"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=16691"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=16691"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}