{"id":10791,"date":"2006-04-25T12:18:00","date_gmt":"2006-04-25T12:18:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/powershell\/2006\/04\/25\/comparative-examples-in-msh-and-ksh\/"},"modified":"2019-02-18T13:25:02","modified_gmt":"2019-02-18T20:25:02","slug":"comparative-examples-in-msh-and-ksh","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/powershell\/comparative-examples-in-msh-and-ksh\/","title":{"rendered":"Comparative Examples in MSH and KSH"},"content":{"rendered":"<div class=\"Section1\">\n<h2>&nbsp;<\/h2>\n<p class=\"MsoNormal\"><font size=\"+1\">M<\/font>ost shells (such as Windows CMD.EXE and the UNIX shells SH, KSH, CSH, and BASH) operate by executing a command or utility in a new process, and presenting the results (or errors) to the user as text. Text-based processing is the way in which system interaction is done with these shells. Over the years, a large number of text processing utilities\u2014such as sed, AWK, and PERL\u2014have evolved to support this interaction. The heritage of this operational process is very rich. <\/p>\n<p class=\"MsoNormal\">MSH is very different from these traditional shells. First, this shell does not use text as the basis for interaction with the system, but uses an object model based on the .NET platform. Second, the list of built-in commands is much larger; this is done to ensure that the interaction with the object model is accomplished with the highest regard to integrity with respect to interacting with the system. Third, the shell provides consistency with regard to interacting with built-in commands through the use of a single parser, rather than relying on each command to create its own parser for parameters. <\/p>\n<p class=\"MsoNormal\">This document constrasts the Korn Shell (KSH) and MSH by providing a number of examples of each. <\/p>\n<p class=\"MsoNormal\"><b>Example 1<\/b><\/p>\n<p class=\"MsoNormal\">To stop all processes that begin with the letter &#8220;p&#8221; on a UNIX system, an administrator would have to type the following shell command line:<\/p>\n<div>\n<p class=\"Snippet\">$ <span class=\"SpellE\"><span class=\"GramE\">ps<\/span><\/span> -e | <span class=\"SpellE\">grep<\/span> &#8221; p&#8221; | <span class=\"SpellE\">awk<\/span> &#8216;{ print $1 }&#8217; | <span class=\"SpellE\">xargs<\/span> kill<\/p>\n<\/div>\n<p class=\"MsoNormal\">The <span class=\"SpellE\"><span class=\"System\">ps<\/span><\/span> command retrieves list of processes and directs (|) the <span class=\"SpellE\"><span class=\"System\">grep<\/span><\/span> command to determine which process begins with &#8220;p&#8221;; which in turn directs (|) the <span class=\"SpellE\"><span class=\"System\">awk<\/span><\/span> command to select the 1st column (which is in the process id) and then passes (|) those to the <span class=\"SpellE\"><span class=\"System\">xargs<\/span><\/span> command which then executes the <span class=\"System\">kill<\/span> command for each process.<span>&nbsp; <\/span>The fragility of this command line may not be evident, but if the <span class=\"SpellE\"><span class=\"System\">ps<\/span><\/span> command behaves differently on different systems, where the &#8220;-e&#8221; flag may not be present, or if the processed command is not in column 1 of the output, this command-line procedure will fail. <\/p>\n<p class=\"MsoNormal\">MSH:<\/p>\n<div>\n<p class=\"Snippet\">MSH&gt; get-process p* | stop-process<\/p>\n<\/div>\n<p class=\"MsoNormal\">Thus, the command line may now be expressed as &#8220;get the processes whose name starts with &#8220;p&#8221; and stop them&#8221;.<span>&nbsp; <\/span>The <span class=\"System\">get-process<\/span> Cmdlet takes an argument that matches the process name; the objects returned by <span class=\"System\">get-process<\/span> are passed directly to the <span class=\"System\">stop-process<\/span> Cmdlet that acts on those objects by stopping them.<\/p>\n<p class=\"MsoNormal\">The second, more convoluted example, which stops processes that use more than 10 MB of <span class=\"GramE\">memory<\/span> becomes quite simple.<\/p>\n<p class=\"MsoNormal\"><b>Example 2<\/b><\/p>\n<p class=\"MsoNormal\">Another, even more complex example, such as &#8220;find the processes that use more than 10 MB of memory and kill them&#8221; can lead to an equally failed outcome:<\/p>\n<div>\n<p class=\"Snippet\">$ <span class=\"SpellE\"><span class=\"GramE\">ps<\/span><\/span> -el | <span class=\"SpellE\">awk<\/span> &#8216;{ if ( $6 &gt; (1024*10)) { print $3 } }&#8217; | <span class=\"SpellE\">grep<\/span> -v PID | <span class=\"SpellE\">xargs<\/span> kill<\/p>\n<\/div>\n<p class=\"MsoNormal\">The success of this command line relies on the user knowing that the <span class=\"SpellE\"><span class=\"System\">ps<\/span><\/span><span class=\"System\"> -el<\/span> command will return the size of the process in kilobytes (kb) in column 6 and that the PID of the process is in column 3.<span>&nbsp; <\/span>It is still required that the first row is removed.<\/p>\n<p class=\"MsoNormal\">Comparing Example 1 using a standard shell to Example 1a using MSH, we can see that the commands act against objects rather than against text.<\/p>\n<p class=\"MsoNormal\">MSH:<\/p>\n<div>\n<p class=\"Snippet\">MSH&gt; get-process | where <span class=\"GramE\">{ $<\/span>_.WS &#8211;<span class=\"SpellE\">gt<\/span> 10MB } | stop-process<\/p>\n<\/div>\n<p class=\"MsoNormal\">There is no issue about determining the column that contains the size of the process, or which column contains the <span class=\"SpellE\">ProcessID<\/span>.<span>&nbsp; <\/span>The memory size may be referred to logically, by its name.<span>&nbsp; <\/span>The <span class=\"System\">where<\/span> Cmdlet can inspect the incoming object directly and refer to its properties.<span>&nbsp; <\/span>The comparison of the value for that property is direct and understandable.<\/p>\n<p class=\"MsoNormal\"><b>Example 3<\/b><\/p>\n<p class=\"MsoNormal\">For example, if you wanted to calculate the number of bytes in the files in a directory, you would iterate over the files, getting the length and adding to a variable, and then print the variable:<\/p>\n<div>\n<p class=\"SnippetCxSpFirst\">$ <span class=\"GramE\">tot=<\/span>0; for file in $( <span class=\"SpellE\">ls<\/span> )<\/p>\n<p class=\"SnippetCxSpMiddle\">&gt; do<\/p>\n<p class=\"SnippetCxSpMiddle\">&gt;<span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>set &#8212; $<span class=\"GramE\">( <span class=\"SpellE\">ls<\/span><\/span> -log $file<span>&nbsp; <\/span>)<\/p>\n<p class=\"SnippetCxSpMiddle\">&gt;<span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>echo $3<\/p>\n<p class=\"SnippetCxSpMiddle\">&gt;<span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>(<span class=\"GramE\">( tot<\/span> = $tot + $3 ))<\/p>\n<p class=\"SnippetCxSpLast\">&gt; done; echo $tot<\/p>\n<\/div>\n<p class=\"MsoNormal\">This example uses the <span class=\"System\">set<\/span> shell command that creates numbered variables for each white space separated element in the line rather than the <span class=\"SpellE\"><span class=\"System\">awk<\/span><\/span> command as in the examples above.<span>&nbsp; <\/span>If the <span class=\"SpellE\"><span class=\"System\">awk<\/span><\/span> command were used, it would be possible to reduce the steps to the following:<\/p>\n<div>\n<p class=\"Snippet\">$ <span class=\"SpellE\"><span class=\"GramE\">ls<\/span><\/span> \u2013l | <span class=\"SpellE\">awk<\/span> \u2018{ tot += $5; print tot; }\u2019 | tail -1<\/p>\n<\/div>\n<p class=\"MsoNormal\">This reduces the complexity, but requires specific knowledge of a new language, the language that is associated with the <span class=\"SpellE\"><span class=\"System\">awk<\/span><\/span> command. <\/p>\n<p class=\"MsoNormal\">The MSH loop is similar; each file in the directory is needed, but it is far simpler as the information about the file is already retrieved:<\/p>\n<p class=\"MsoNormal\">MSH:<\/p>\n<div>\n<p class=\"Snippet\">MSH&gt; get-<span class=\"SpellE\">childitem<\/span> | measure-object -Property length -Sum<\/p>\n<\/div>\n<p class=\"MsoNormal\">The <span class=\"System\">measure-object<\/span> Cmdlet interacts with objects and if it is provided with a property from the object, it will sum the values of that property.<span>&nbsp; <\/span>Because the property length represents the length of the file, the <span class=\"System\">measure-object<\/span> Cmdlet is able to act directly on the object by referring to the property name rather than \u201cknowing\u201d that the length of the file is in column 3 or column 5.<\/p>\n<p class=\"MsoNormal\"><b>Example 4<\/b><\/p>\n<p class=\"MsoNormal\">Many objects provided by the system are not static, but dynamic.<span>&nbsp; <\/span>This means that after an object is acquired, it is not necessary to acquire the object at a later time.<span>&nbsp; <\/span>The data in the object is updated as the conditions of the system change.<span>&nbsp; <\/span>Also, changes to these objects are reflected immediately in the system.<\/p>\n<p class=\"MsoNormal\">As an example, suppose one wanted to collect the amount of processor time that a process used over time.<span>&nbsp; <\/span>In the traditional UNIX model, the <span class=\"SpellE\"><span class=\"System\">ps<\/span><\/span> command would need to be run iteratively and the appropriate column in the output would need to be found and then the subtraction would need to be done.<span>&nbsp; <\/span>With a shell that is able to access the process object of the system, it is possible to acquire the process object once, and since this object is continually updated by the system; all that is necessary is to refer to the property.<span>&nbsp; <\/span>The following examples illustrate the differences, where the memory size of an application is checked in ten second intervals and the differences are output:<\/p>\n<div>\n<p class=\"SnippetCxSpFirst\">$ <span class=\"GramE\">while<\/span> [ true ]<\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"GramE\">do<\/span><\/p>\n<p class=\"SnippetCxSpMiddle\"><span>&nbsp;&nbsp; <\/span>msize1=$( <span class=\"SpellE\">ps<\/span> -el | <span class=\"SpellE\">grep<\/span> application | <span class=\"SpellE\">grep<\/span> -v <span class=\"SpellE\">grep<\/span> | <span class=\"SpellE\">awk<\/span> &#8216;{<span>&nbsp; <\/span>print $6 }&#8217; )<\/p>\n<p class=\"SnippetCxSpMiddle\"><span>&nbsp;&nbsp; <\/span><span class=\"GramE\">sleep<\/span> 10<\/p>\n<p class=\"SnippetCxSpMiddle\"><span>&nbsp;&nbsp; <\/span>msize2=$<span class=\"GramE\">( <span class=\"SpellE\">ps<\/span><\/span> -el | <span class=\"SpellE\">grep<\/span> application | <span class=\"SpellE\">grep<\/span> -v <span class=\"SpellE\">grep<\/span> | <span class=\"SpellE\">awk<\/span> &#8216;{<span>&nbsp; <\/span>print $6 }&#8217; )<\/p>\n<p class=\"SnippetCxSpMiddle\"><span>&nbsp;&nbsp; <\/span><span class=\"SpellE\"><span class=\"GramE\">expr<\/span><\/span> $msize2 &#8211; $msize1<\/p>\n<p class=\"SnippetCxSpMiddle\"><span>&nbsp;&nbsp; <\/span>msize1=$msize2<\/p>\n<p class=\"SnippetCxSpLast\"><span class=\"GramE\">done<\/span><\/p>\n<\/div>\n<p class=\"MsoNormal\">MSH:<\/p>\n<div>\n<p class=\"SnippetCxSpFirst\">MSH&gt; $app = get-process application<\/p>\n<p class=\"SnippetCxSpMiddle\">MSH&gt; while <span class=\"GramE\">( 1<\/span> ) {<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span><\/p>\n<p class=\"SnippetCxSpMiddle\">&gt;&gt; $msize1 = $<span class=\"SpellE\">app.VS<\/span><\/p>\n<p class=\"SnippetCxSpMiddle\">&gt;&gt; <span class=\"GramE\">start-sleep<\/span> 10<\/p>\n<p class=\"SnippetCxSpMiddle\">&gt;&gt; $<span class=\"SpellE\">app.VS<\/span> &#8211; $msize1<span>&nbsp;&nbsp; <\/span><\/p>\n<p class=\"SnippetCxSpLast\">&gt;&gt; }<\/p>\n<\/div>\n<p class=\"MsoNormal\"><b>Example 5<\/b><\/p>\n<p class=\"MsoNormal\">It is even more difficult to determine whether a specific process is no longer running.<span>&nbsp; <\/span>In this case, the UNIX user must collect the list of processes and compare them to another list.<span>&nbsp; <\/span><\/p>\n<div>\n<p class=\"StyleSnippet8ptCxSpFirst\">$ <span class=\"SpellE\"><span class=\"GramE\">processToWatch<\/span><\/span>=$( <span class=\"SpellE\">ps<\/span> -e | <span class=\"SpellE\">grep<\/span> application | <span class=\"SpellE\">awk<\/span> &#8216;{ print $1 }&#8217;<\/p>\n<p class=\"StyleSnippet8ptCxSpMiddle\">$ <span class=\"GramE\">while<\/span> [ true ]<\/p>\n<p class=\"StyleSnippet8ptCxSpMiddle\">&gt; do<\/p>\n<p class=\"StyleSnippet8ptCxSpMiddle\">&gt;<span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>sleep 10<\/p>\n<p class=\"StyleSnippet8ptCxSpMiddle\">&gt;<span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span class=\"SpellE\"><span class=\"GramE\">processToCheck<\/span><\/span>=$(<span class=\"SpellE\">ps<\/span> -e | <span class=\"SpellE\">grep<\/span> application | <span class=\"SpellE\">awk<\/span> &#8216;{ print $1 }&#8217; )<\/p>\n<p class=\"StyleSnippet8ptCxSpMiddle\">&gt;<span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span class=\"GramE\">if<\/span> [ -z &#8220;$<span class=\"SpellE\">processToCheck<\/span>&#8221; -or &#8220;$<span class=\"SpellE\">processToWatch<\/span>&#8221; != &#8220;$<span class=\"SpellE\">processToCheck<\/span>&#8221; ]<\/p>\n<p class=\"StyleSnippet8ptCxSpMiddle\">&gt;<span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span class=\"GramE\">then<\/span><\/p>\n<p class=\"StyleSnippet8ptCxSpMiddle\">&gt;<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>echo &#8220;Process application is not running&#8221;<\/p>\n<p class=\"StyleSnippet8ptCxSpMiddle\">&gt;<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>return<\/p>\n<p class=\"StyleSnippet8ptCxSpMiddle\">&gt;<span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span><span class=\"SpellE\"><span class=\"GramE\">fi<\/span><\/span><\/p>\n<p class=\"StyleSnippet8ptCxSpLast\">&gt; done<\/p>\n<\/div>\n<p class=\"MsoNormal\">MSH:<\/p>\n<div>\n<p class=\"SnippetCxSpFirst\">MSH&gt; $<span class=\"SpellE\">processToWatch<\/span> = get-process application<\/p>\n<p class=\"SnippetCxSpLast\">MSH&gt; $<span class=\"SpellE\"><span class=\"GramE\">processToWatch.WaitForExit<\/span><\/span><span class=\"GramE\">()<\/span><\/p>\n<\/div>\n<p class=\"MsoNormal\">As is seen in this example, the MSH user need only collect the object and then subsequently refer to that object.<span>&nbsp; <\/span><\/p>\n<p class=\"MsoNormal\"><b>Example 6<\/b><\/p>\n<p class=\"MsoNormal\">For example, suppose the user wanted to determine which processes were compiled as <span class=\"SpellE\">PreRelease<\/span> code, such as when applications have been compiled in such a way to mark them as &#8220;<span class=\"SpellE\">PreRelease<\/span>&#8220;.<\/p>\n<div>\n<p class=\"Snippet\">$ ???<\/p>\n<\/div>\n<p class=\"MsoNormal\">This information is not kept in the standard UNIX executable.<span>&nbsp; <\/span>To determine this information, one would need to have a set of specialized utilities to add this information to the binary and then another set of utilities to collect this information.<span>&nbsp; <\/span>These utilities do not exist; it is not possible to accomplish this task.<\/p>\n<p class=\"MsoNormal\">MSH:<\/p>\n<div>\n<p class=\"SnippetCxSpFirst\">MSH&gt; get-process | where {$_.<span class=\"SpellE\">mainmodule.FileVersioninfo.isPreRelease<\/span>}<\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"GramE\">Handles<span>&nbsp; <\/span>NPM<\/span>(K)<span>&nbsp;&nbsp;&nbsp; <\/span>PM(K)<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>WS(K) VS(M)<span>&nbsp;&nbsp; <\/span>CPU(s)<span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>Id <span class=\"SpellE\">ProcessName<\/span><\/p>\n<p class=\"SnippetCxSpMiddle\">&#8212;&#8212;-<span>&nbsp; <\/span>&#8212;&#8212;<span>&nbsp;&nbsp;&nbsp; <\/span>&#8212;&#8211;<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>&#8212;&#8211; &#8212;&#8211;<span>&nbsp;&nbsp; <\/span>&#8212;&#8212;<span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>&#8212; &#8212;&#8212;&#8212;&#8211;<\/p>\n<p class=\"SnippetCxSpMiddle\"><span>&nbsp;&nbsp;&nbsp; <\/span>643<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>88<span>&nbsp;&nbsp;&nbsp;&nbsp; <\/span>1024<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>1544<span>&nbsp;&nbsp;&nbsp; <\/span>15<span>&nbsp;&nbsp;&nbsp; <\/span>14.06<span>&nbsp;&nbsp; <\/span>1700 <span class=\"SpellE\">AdtAgent<\/span><\/p>\n<p class=\"SnippetCxSpLast\"><span>&nbsp;&nbsp;&nbsp; <\/span>453<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>15<span>&nbsp;&nbsp;&nbsp; <\/span>25280<span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <\/span>7268<span>&nbsp;&nbsp; <\/span>199<span>&nbsp;&nbsp;&nbsp; <\/span>91.70<span>&nbsp;&nbsp; <\/span>3952 <span class=\"SpellE\">devenv<\/span><\/p>\n<\/div>\n<p class=\"MsoNormal\">In this example, a cascade of properties is done.<span>&nbsp; <\/span>The appropriate property from the process object (<span class=\"SpellE\">MainModule<\/span>) is inspected, the property &#8220;<span class=\"SpellE\">FileVersionInfo<\/span>&#8221; is referenced (a property of <span class=\"SpellE\">MainModule<\/span>) and the value of the property &#8220;<span class=\"SpellE\">IsPreRelease<\/span>&#8221; is used to filter the results.<span>&nbsp; <\/span>If <span class=\"SpellE\">IsPreRelease<\/span> is true, the objects that are output by the <span class=\"System\">get-process<\/span> Cmdlet are output.<\/p>\n<p class=\"MsoNormal\"><b>Example 7<\/b><\/p>\n<p class=\"MsoNormal\">Each object may or may not provide methods; MSH provides commands to aid the discovery of methods that are available for a specific object via the <span class=\"System\">get-member<\/span> Cmdlet.<span>&nbsp; <\/span>For example, the string object has a large number of methods:<\/p>\n<p class=\"MsoNormal\">MSH:<\/p>\n<div>\n<p class=\"SnippetCxSpFirst\">MSH&gt; get-member -input &#8220;String&#8221; &#8211;<span class=\"SpellE\">membertype<\/span> method | format-table &#8220;$_&#8221;<\/p>\n<p class=\"SnippetCxSpMiddle\">&#8220;$_&#8221;<\/p>\n<p class=\"SnippetCxSpMiddle\">&#8212;&#8212;&#8212;<\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.Object<\/span> <span class=\"GramE\">Clone()<\/span><\/p>\n<p class=\"SnippetCxSpMiddle\">Int32 <span class=\"GramE\">Compare(<\/span><span class=\"SpellE\">System.String<\/span>, <span class=\"SpellE\">System.String<\/span>, Boolean, <span class=\"SpellE\">System.Globalization.Cul<\/span>..<\/p>\n<p class=\"SnippetCxSpMiddle\">Int32 <span class=\"SpellE\"><span class=\"GramE\">CompareOrdinal<\/span><\/span><span class=\"GramE\">(<\/span><span class=\"SpellE\">System.String<\/span>, Int32, <span class=\"SpellE\">System.String<\/span>, Int32, Int32)<\/p>\n<p class=\"SnippetCxSpMiddle\">Int32 <span class=\"SpellE\"><span class=\"GramE\">CompareTo<\/span><\/span><span class=\"GramE\">(<\/span><span class=\"SpellE\">System.String<\/span>)<\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.String<\/span> <span class=\"SpellE\"><span class=\"GramE\">Concat<\/span><\/span><span class=\"GramE\">(<\/span><span class=\"SpellE\">System.String<\/span>, <span class=\"SpellE\">System.String<\/span>)<\/p>\n<p class=\"SnippetCxSpMiddle\">Boolean <span class=\"GramE\">Contains(<\/span><span class=\"SpellE\">System.String<\/span>)<\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.String<\/span> <span class=\"GramE\">Copy(<\/span><span class=\"SpellE\">System.String<\/span>)<\/p>\n<p class=\"SnippetCxSpMiddle\">Void <span class=\"SpellE\"><span class=\"GramE\">CopyTo<\/span><\/span><span class=\"GramE\">(<\/span>Int32, Char[], Int32, Int32)<\/p>\n<p class=\"SnippetCxSpMiddle\">Boolean <span class=\"SpellE\"><span class=\"GramE\">EndsWith<\/span><\/span><span class=\"GramE\">(<\/span><span class=\"SpellE\">System.String<\/span>, Boolean, <span class=\"SpellE\">System.Globalization.CultureInfo<\/span>)<\/p>\n<p class=\"SnippetCxSpMiddle\">Boolean <span class=\"GramE\">Equals(<\/span><span class=\"SpellE\">System.String<\/span>, <span class=\"SpellE\">System.StringComparison<\/span>)<\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.String<\/span> <span class=\"GramE\">Format(<\/span><span class=\"SpellE\">System.String<\/span>, <span class=\"SpellE\">System.Object<\/span>, <span class=\"SpellE\">System.Object<\/span>)<\/p>\n<p class=\"SnippetCxSpMiddle\">Char <span class=\"SpellE\">get_<span class=\"GramE\">Chars<\/span><\/span><span class=\"GramE\">(<\/span>Int32)<\/p>\n<p class=\"SnippetCxSpMiddle\">Int32 <span class=\"SpellE\">get_<span class=\"GramE\">Length<\/span><\/span><span class=\"GramE\">()<\/span><\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.CharEnumerator<\/span> <span class=\"SpellE\"><span class=\"GramE\">GetEnumerator<\/span><\/span><span class=\"GramE\">()<\/span><\/p>\n<p class=\"SnippetCxSpMiddle\">Int32 <span class=\"SpellE\"><span class=\"GramE\">GetHashCode<\/span><\/span><span class=\"GramE\">()<\/span><\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.Type<\/span> <span class=\"SpellE\"><span class=\"GramE\">GetType<\/span><\/span><span class=\"GramE\">()<\/span><\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.TypeCode<\/span> <span class=\"SpellE\"><span class=\"GramE\">GetTypeCode<\/span><\/span><span class=\"GramE\">()<\/span><\/p>\n<p class=\"SnippetCxSpMiddle\">Int32 <span class=\"SpellE\"><span class=\"GramE\">IndexOf<\/span><\/span><span class=\"GramE\">(<\/span><span class=\"SpellE\">System.String<\/span>, Int32)<\/p>\n<p class=\"SnippetCxSpMiddle\">Int32 <span class=\"SpellE\"><span class=\"GramE\">IndexOfAny<\/span><\/span><span class=\"GramE\">(<\/span>Char[], Int32, Int32)<\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.String<\/span> <span class=\"GramE\">Insert(<\/span>Int32, <span class=\"SpellE\">System.String<\/span>)<\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.String<\/span> <span class=\"GramE\">Intern(<\/span><span class=\"SpellE\">System.String<\/span>)<\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.String<\/span> <span class=\"SpellE\"><span class=\"GramE\">IsInterned<\/span><\/span><span class=\"GramE\">(<\/span><span class=\"SpellE\">System.String<\/span>)<\/p>\n<p class=\"SnippetCxSpMiddle\">Boolean <span class=\"SpellE\"><span class=\"GramE\">IsNormalized<\/span><\/span><span class=\"GramE\">()<\/span><\/p>\n<p class=\"SnippetCxSpMiddle\">Boolean <span class=\"SpellE\"><span class=\"GramE\">IsNullOrEmpty<\/span><\/span><span class=\"GramE\">(<\/span><span class=\"SpellE\">System.String<\/span>)<\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.String<\/span> <span class=\"GramE\">Join(<\/span><span class=\"SpellE\">System.String<\/span>, <span class=\"SpellE\">System.String<\/span>[])<\/p>\n<p class=\"SnippetCxSpMiddle\">Int32 <span class=\"SpellE\"><span class=\"GramE\">LastIndexOf<\/span><\/span><span class=\"GramE\">(<\/span>Char, Int32)<\/p>\n<p class=\"SnippetCxSpMiddle\">Int32 <span class=\"SpellE\"><span class=\"GramE\">LastIndexOfAny<\/span><\/span><span class=\"GramE\">(<\/span>Char[], Int32)<\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.String<\/span> <span class=\"GramE\">Normalize(<\/span><span class=\"SpellE\">System.Text.NormalizationForm<\/span>)<\/p>\n<p class=\"SnippetCxSpMiddle\">Boolean <span class=\"SpellE\">op_<span class=\"GramE\">Equality<\/span><\/span><span class=\"GramE\">(<\/span><span class=\"SpellE\">System.String<\/span>, <span class=\"SpellE\">System.String<\/span>)<\/p>\n<p class=\"SnippetCxSpMiddle\">Boolean <span class=\"SpellE\">op_<span class=\"GramE\">Inequality<\/span><\/span><span class=\"GramE\">(<\/span><span class=\"SpellE\">System.String<\/span>, <span class=\"SpellE\">System.String<\/span>)<\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.String<\/span> <span class=\"SpellE\"><span class=\"GramE\">PadLeft<\/span><\/span><span class=\"GramE\">(<\/span>Int32, Char)<\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.String<\/span> <span class=\"SpellE\"><span class=\"GramE\">PadRight<\/span><\/span><span class=\"GramE\">(<\/span>Int32, Char)<\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.String<\/span> <span class=\"GramE\">Remove(<\/span>Int32)<\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.String<\/span> <span class=\"GramE\">Replace(<\/span><span class=\"SpellE\">System.String<\/span>, <span class=\"SpellE\">System.String<\/span>)<\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\"><span class=\"GramE\">System.String<\/span><\/span><span class=\"GramE\">[<\/span>] Split(<span class=\"SpellE\">System.String<\/span>[], <span class=\"SpellE\">System.StringSplitOptions<\/span>)<\/p>\n<p class=\"SnippetCxSpMiddle\">Boolean <span class=\"SpellE\"><span class=\"GramE\">StartsWith<\/span><\/span><span class=\"GramE\">(<\/span><span class=\"SpellE\">System.String<\/span>)<\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.String<\/span> <span class=\"GramE\">Substring(<\/span>Int32)<\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"GramE\">Char[<\/span>] <span class=\"SpellE\">ToCharArray<\/span>(Int32, Int32)<\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.String<\/span> <span class=\"SpellE\"><span class=\"GramE\">ToLower<\/span><\/span><span class=\"GramE\">()<\/span><\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.String<\/span> <span class=\"SpellE\"><span class=\"GramE\">ToLowerInvariant<\/span><\/span><span class=\"GramE\">()<\/span><\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.String<\/span> <span class=\"SpellE\"><span class=\"GramE\">ToString<\/span><\/span><span class=\"GramE\">(<\/span><span class=\"SpellE\">System.IFormatProvider<\/span>)<\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.String<\/span> <span class=\"SpellE\"><span class=\"GramE\">ToUpper<\/span><\/span><span class=\"GramE\">(<\/span><span class=\"SpellE\">System.Globalization.CultureInfo<\/span>)<\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.String<\/span> <span class=\"SpellE\"><span class=\"GramE\">ToUpperInvariant<\/span><\/span><span class=\"GramE\">()<\/span><\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.String<\/span> <span class=\"GramE\">Trim()<\/span><\/p>\n<p class=\"SnippetCxSpMiddle\"><span class=\"SpellE\">System.String<\/span> <span class=\"SpellE\"><span class=\"GramE\">TrimEnd<\/span><\/span><span class=\"GramE\">(<\/span>Char[])<\/p>\n<p class=\"SnippetCxSpLast\"><span class=\"SpellE\">System.String<\/span> <span class=\"SpellE\"><span class=\"GramE\">TrimStart<\/span><\/span><span class=\"GramE\">(<\/span>Char[])<\/p>\n<\/div>\n<p class=\"MsoNormal\">As can be seen, 46 different methods are available to the string object all of which are available to the MSH user.<span>&nbsp; <\/span>Unfortunately, the semantics of these methods is not visible from the shell, but a number of .NET object help is available online. <\/p>\n<p class=\"MsoNormal\"><b>Example 8<\/b><\/p>\n<p class=\"MsoNormal\">The availability of these methods creates an explosion of possibilities.<span>&nbsp; <\/span>For example, if I wanted to change the case of a string from lower to upper I would do the following: (first <span class=\"SpellE\">ksh<\/span> and then MSH).<\/p>\n<div>\n<p class=\"Snippet\">$ echo &#8220;this is a string&#8221; | <span class=\"SpellE\">tr<\/span> [<span class=\"GramE\">:lower<\/span>:] [:upper:]<\/p>\n<\/div>\n<p class=\"MsoNormal\"><span class=\"GramE\">or<\/span><\/p>\n<div>\n<p class=\"Snippet\">$ echo &#8220;this is a string&#8221; | <span class=\"SpellE\"><span class=\"GramE\">tr<\/span><\/span> &#8216;[a-z]&#8217; <span class=\"SpellE\">&#8216;<\/span>[A-Z]&#8217;<\/p>\n<\/div>\n<p class=\"MsoNormal\">MSH:<\/p>\n<div>\n<p class=\"Snippet\">MSH&gt; &#8220;this is a <span class=\"SpellE\">string&#8221;.<span class=\"GramE\">ToUpper<\/span><\/span><span class=\"GramE\">()<\/span><\/p>\n<\/div>\n<p class=\"MsoNormal\">The UNIX example relies on the <span class=\"SpellE\"><span class=\"GramE\"><span class=\"System\">tr<\/span><\/span><\/span> cmdlet.<span>&nbsp; <\/span><\/p>\n<p class=\"MsoNormal\"><b>Example 9<\/b><\/p>\n<p class=\"MsoNormal\">For example, suppose the string &#8220;ABC&#8221; was to be inserted after the first character in the word &#8220;string&#8221; to have the result &#8220;<span class=\"SpellE\">sABCtring<\/span>&#8220;.<span>&nbsp; <\/span>Here are the following, first with <span class=\"SpellE\">ksh<\/span>, then with MSH:<\/p>\n<div>\n<p class=\"Snippet\">$ echo &#8220;string&#8221; | <span class=\"SpellE\">sed<\/span> &#8220;s|<span class=\"GramE\">\\(<\/span>.\\)\\(.*)|\\1ABC\\2|&#8221;<\/p>\n<\/div>\n<p class=\"MsoNormal\">MSH:<\/p>\n<div>\n<p class=\"Snippet\">MSH&gt; &#8220;<span class=\"SpellE\">string&#8221;.<span class=\"GramE\">Insert<\/span><\/span><span class=\"GramE\">(<\/span>1,&#8221;ABC&#8221;)<\/p>\n<\/div>\n<p class=\"MsoNormal\">Both examples require specific knowledge; however, using the &#8220;insert&#8221; method is more intuitive than using the capture buffers available in <span class=\"SpellE\">sed<\/span>.<span>&nbsp; <\/span>Moreover, the domain specific knowledge of the &#8220;<span class=\"SpellE\">sed<\/span>&#8221; language required may be somewhat more advanced than is required to use the Insert method.<\/p>\n<hr \/>\n<p><\/p>\n<p class=\"MsoNormal\">Jim Truher and Jeffrey Snover<\/p>\n<\/div>\n<p>[<i>Edit: Monad has now been renamed to Windows PowerShell. This script or discussion may require slight adjustments before it applies directly to newer builds.<\/i>]<\/p>\n<p>PSMDTAG:FAQ: KSH BASH&nbsp;&#8211; how does PowerShell compare to KSH and BASH?<br \/>PSMDTAG:DOTNET: Leverage System.String to do KSH\/BASH type functions.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&nbsp; Most shells (such as Windows CMD.EXE and the UNIX shells SH, KSH, CSH, and BASH) operate by executing a command or utility in a new process, and presenting the results (or errors) to the user as text. Text-based processing is the way in which system interaction is done with these shells. Over the years, [&hellip;]<\/p>\n","protected":false},"author":600,"featured_media":13641,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[1],"tags":[14,10,21],"class_list":["post-10791","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-powershell","tag-dotnet","tag-faq","tag-shell"],"acf":[],"blog_post_summary":"<p>&nbsp; Most shells (such as Windows CMD.EXE and the UNIX shells SH, KSH, CSH, and BASH) operate by executing a command or utility in a new process, and presenting the results (or errors) to the user as text. Text-based processing is the way in which system interaction is done with these shells. Over the years, [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/10791","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/users\/600"}],"replies":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/comments?post=10791"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/10791\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media\/13641"}],"wp:attachment":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/media?parent=10791"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/categories?post=10791"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/tags?post=10791"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}