{"id":10741,"date":"2006-04-25T12:18:00","date_gmt":"2006-04-25T12:18:00","guid":{"rendered":"https:\/\/blogs.msdn.microsoft.com\/powershell\/2006\/04\/25\/how-does-select-string-work-with-pipelines-of-objects\/"},"modified":"2019-02-18T13:25:00","modified_gmt":"2019-02-18T20:25:00","slug":"how-does-select-string-work-with-pipelines-of-objects","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/powershell\/how-does-select-string-work-with-pipelines-of-objects\/","title":{"rendered":"How does Select-String work with Pipelines of objects?"},"content":{"rendered":"<p>&lt;Edited to convert Match-String to Select-String 7\/9\/2006&gt;<\/p>\n<p>In&nbsp;our newsgroup (Microsoft.Public.Windows.Server.Scripting) , Vasu asked about how Select-string works in pipelines:<\/p>\n<blockquote>\n<p>Here is what I observe:<br \/>1. MSH C:\\&gt; get-alias<br \/>&nbsp;..truncated..<br \/>Alias&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ri&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; remove-item<br \/>Alias&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rni&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; rename-item<br \/>..truncated..<\/p>\n<p>2. MSH C:\\&gt; get-alias | select-string ri<br \/>ri<br \/>MSH C:\\&gt;<\/p>\n<\/blockquote>\n<p>The question is why did the string &#8220;ri&#8221; get emitted instead of the alias record.<\/p>\n<p dir=\"ltr\">So what is going on here?<\/p>\n<p dir=\"ltr\">Select-String works on Streams of STRINGS.&nbsp; When you pass it a string of OBJECTS, the MONAD engine converts those objects to strings before passing them to Select-String.&nbsp; Thus the following 2 commands are functionaly equivalent:<\/p>\n<p dir=\"ltr\"><font face=\"Courier New\" size=\"2\">get-alias | select-string &#8220;ri&#8221;<br \/>get-alias | foreach {&#8220;$_&#8221;} |Select-string &#8220;ri&#8221;<\/font><\/p>\n<p dir=\"ltr\">Converting an object to a string is accomplished by call that object&#8217;s ToString() method (vs using MONAD&#8217;s formating subsystem).&nbsp; Notice the difference &#8211; the first uses Monad&#8217;s formating and the second is the object&#8217;s ToString()&nbsp;<\/p>\n<p dir=\"ltr\"><font face=\"Courier New\" size=\"2\">MSH&gt; (gal ri)<\/font><\/p>\n<p dir=\"ltr\"><font face=\"Courier New\" size=\"2\">CommandType&nbsp;&nbsp;&nbsp;&nbsp; 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; Definition<br \/>&#8212;&#8212;&#8212;&#8211;&nbsp;&nbsp;&nbsp;&nbsp; &#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; &#8212;&#8212;&#8212;-<br \/>Alias&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ri&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; remove-item<\/font><\/p>\n<p dir=\"ltr\"><font face=\"Courier New\" size=\"2\">MSH&gt; (gal ri).ToString()<br \/>ri<br \/>MSH&gt;<\/font><\/p>\n<p dir=\"ltr\">If you wanted Select-String to work on the Monad formatted output, you&#8217;ll need to get that as a string.&nbsp; Here is the thing to grok about our outputing.&nbsp; When your command sequence emits a stream of strings, we emit it without processing.&nbsp; If&nbsp; instead, your command sequence emits a stream of objects, then we redirect those objects to the command Out-Default.&nbsp; Out-Default looks at the type of the object and the registered formating metadata to see if there is a default view for that object type.&nbsp; A view defines a FORMATTER and the metadata for that command.&nbsp; Most objects get vectored to either Format-Table or Format-List (though they could go to Format-Wide or Format-Custom).&nbsp; THESE FORMATTERS DO <strong>NOT<\/strong> EMIT STRINGS!&nbsp; You can see this for yourself by the following: <\/p>\n<p dir=\"ltr\"><font face=\"Courier New\" size=\"2\">MSH&gt; gps |ft |group {$_.GetType().name} |ft Count,Name -auto<\/font><\/p>\n<p dir=\"ltr\"><font face=\"Courier New\" size=\"2\">Count Name<br \/>&#8212;&#8211; &#8212;-<br \/>&nbsp;&nbsp;&nbsp; 1 FormatStartData<br \/>&nbsp;&nbsp;&nbsp; 1 GroupStartData<br \/>&nbsp;&nbsp; 53 FormatEntryData<br \/>&nbsp;&nbsp;&nbsp; 1 GroupEndData<br \/>&nbsp;&nbsp;&nbsp; 1 FormatEndData<\/font><\/p>\n<p dir=\"ltr\">These formating records are then vectored to an OUT-xxx command to be rendered into the appropriate data for a particular output device.&nbsp; By default, they go to Out-Host but you can pipe this to Out-File, Out-Printer or Out-String.&nbsp; (NOTE: these OUT-xxx commands are pretty clever, if you pipe formating objects to them, they&#8217;ll render them.&nbsp; If you pipe raw object to them, they&#8217;ll first call the appropriate formatter and then render them.)<\/p>\n<p dir=\"ltr\">So to make Select-string work against the string version of Monad&#8217;s output, you&#8217;d do this:<\/p>\n<p><font face=\"Courier New\" size=\"2\">MSH&gt; get-alias | out-string -stream | Select-string &#8220;ri&#8221;<br \/>Alias&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clv&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; clear-variable<br \/>Alias&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gdr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get-drive<br \/>Alias&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; gv&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; get-variable<br \/>Alias&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ndr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new-drive<br \/>Alias&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; nv&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; new-variable<br \/>Alias&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rdr&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; remove-drive<br \/>Alias&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ri&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; remove-item<br \/>Alias&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rv&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; remove-variable<br \/>&#8230;<\/font><\/p>\n<p><font face=\"Courier New\" size=\"2\">Notice a couple things 1) you had to say &#8220;Out-String -STREAM&#8221; (if you didn&#8217;t say -STREAM you would have gotten a single string) 2) now Select-string matches any line that has an &#8220;ri&#8221; in it not just the ones where&nbsp;the NAME&nbsp;has an &#8220;ri&#8221; in it.<\/font><\/p>\n<p><font face=\"Courier New\" size=\"2\">Think about the last statement &#8216;just the ones where the NAME has an &#8220;ri&#8221; in it&#8217;.&nbsp; One of the things we designed Monad to do was to give you an experience where you think it, you type it, you get it.&nbsp; So let&#8217;s say it, &#8220;I want to GET the ALIASes WHERE the NAME matches the string RI&#8221;.&nbsp; Now lets type it:<\/font><\/p>\n<p><font face=\"Courier New\" size=\"2\">MSH&gt; GET-ALIAS |WHERE {$_.NAME -match &#8220;ri&#8221;}<\/font><\/p>\n<p><font face=\"Courier New\" size=\"2\">CommandType&nbsp;&nbsp;&nbsp;&nbsp; Name&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Definition<br \/>&#8212;&#8212;&#8212;&#8211;&nbsp;&nbsp;&nbsp;&nbsp; &#8212;-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8212;&#8212;&#8212;-<br \/>Alias&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ri&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; remove-item<br \/>Alias&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; write&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; write-object<\/font><\/p>\n<p>It take a while to stop thinking in terms of streams of text and start thinking in terms of streams of objects.&nbsp; The benefit is that once you do this, you begin to ask questions in a way that makes it really easy to answer.<\/p>\n<p>Enjoy!<\/p>\n<p>Jeffrey Snover<br \/>Monad Architect<\/p>\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: How does Select-String work with objects?<\/p>\n<p>PSMDTAG:FAQ: How does outputing (i.e. out-default) work?<\/p>\n<p>PSMDTAG:PHILOSOPHY: Stop thinking in terms of streams of text and start thinking of streams of objects<\/p>\n<p>PSMDTAG:CMDLET: Get-Alias, Select-String<\/p>\n<p>PSMDTAG:CMDLET:FORMAT: out-default, out-string -stream<\/p>\n<p>PSMDTAG:INTERNAL: Formatters do NOT emit strings, they emit format records<\/p>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>&lt;Edited to convert Match-String to Select-String 7\/9\/2006&gt; In&nbsp;our newsgroup (Microsoft.Public.Windows.Server.Scripting) , Vasu asked about how Select-string works in pipelines: Here is what I observe:1. MSH C:\\&gt; get-alias&nbsp;..truncated..Alias&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ri&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; remove-itemAlias&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rni&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; rename-item..truncated.. 2. MSH C:\\&gt; get-alias | select-string ririMSH C:\\&gt; The question is why did the string &#8220;ri&#8221; get emitted instead of the alias record. So [&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":[10,11,16],"class_list":["post-10741","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-powershell","tag-faq","tag-philosophy","tag-select-string"],"acf":[],"blog_post_summary":"<p>&lt;Edited to convert Match-String to Select-String 7\/9\/2006&gt; In&nbsp;our newsgroup (Microsoft.Public.Windows.Server.Scripting) , Vasu asked about how Select-string works in pipelines: Here is what I observe:1. MSH C:\\&gt; get-alias&nbsp;..truncated..Alias&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; ri&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; remove-itemAlias&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rni&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; rename-item..truncated.. 2. MSH C:\\&gt; get-alias | select-string ririMSH C:\\&gt; The question is why did the string &#8220;ri&#8221; get emitted instead of the alias record. So [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/10741","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=10741"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/posts\/10741\/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=10741"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/categories?post=10741"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/powershell\/wp-json\/wp\/v2\/tags?post=10741"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}