{"id":12201,"date":"2011-11-03T00:01:00","date_gmt":"2011-11-03T00:01:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2011\/11\/03\/search-for-and-replace-words-in-a-csv-file-by-using-powershell\/"},"modified":"2011-11-03T00:01:00","modified_gmt":"2011-11-03T00:01:00","slug":"search-for-and-replace-words-in-a-csv-file-by-using-powershell","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/search-for-and-replace-words-in-a-csv-file-by-using-powershell\/","title":{"rendered":"Search for and Replace Words in a CSV File by Using PowerShell"},"content":{"rendered":"<p><span style=\"font-size: small\"><span style=\"font-family: Segoe\"><strong>Summary:<\/strong> Learn how to search for and replace words in a CSV file by using Windows PowerShell.<\/span><\/span><\/p>\n<p class=\"CodeBlock\"><span style=\"font-family: Lucida Sans Typewriter;font-size: small\">&nbsp;<\/span><\/p>\n<p><span style=\"font-family: Segoe;font-size: small\"><span style=\"font-size: small\"><span style=\"font-family: Segoe\"><span style=\"font-family: Segoe;font-size: small\"><span style=\"font-family: Segoe\"><img decoding=\"async\" title=\"Hey, Scripting Guy! Question\" border=\"0\" alt=\"Hey, Scripting Guy! Question\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" height=\"34\" \/><\/span><\/span><\/span><\/span>Hey, Scripting Guy! I have a comma-separated value (CSV) file that contains user names, user groups, and organizational unit (OU) assignments. The problem is that we are moving one of our office locations, and I need to quickly change the old location name to the new location name. I have been reading all of your articles this week, and I think I should be able to use <b>Import-CSV<\/b> to read the CSV file, and use a <b>foreach<\/b> loop to evaluate each row in the CSV file. <\/span><\/p>\n<p><span style=\"font-family: Segoe;font-size: small\">Inside there, I should be able to use an <b>if<\/b><i> <\/i>statement to see if there is a match with the old name. If there is, I want to change it to the new name, and then export the CSV data to a new file. The problem is that this is not really working the way I want it to. For some reason, I appear to be picking up some kind of extra crap that is added by Windows PowerShell. I have spent all afternoon on something that should really be a simple one-liner. Help please. If I have to write a script to do this, I may as well go back to using VBScript. At least I have plenty of years experience using that language. <\/span><\/p>\n<p><span style=\"font-family: Segoe;font-size: small\">&mdash;GM<\/span><\/p>\n<p><span style=\"font-family: Segoe;font-size: small\">&nbsp;<\/span><\/p>\n<p><span style=\"font-family: Segoe;font-size: small\"><span style=\"font-family: Segoe;font-size: small\"><span style=\"font-family: Segoe;font-size: small\"><span style=\"font-family: Segoe\"><img decoding=\"async\" title=\"Hey, Scripting Guy! Answer\" border=\"0\" alt=\"Hey, Scripting Guy! Answer\" align=\"left\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" height=\"34\" \/><\/span><\/span><\/span>Hello GM, <\/span><\/p>\n<p><span style=\"font-size: small\"><span style=\"font-family: Segoe\">Microsoft Scripting Guy Ed Wilson here. One thing that is rather interesting about Windows PowerShell is that some things are really super easy. Other things appear to be difficult until you find the &ldquo;correct&rdquo; approach. One of the things I noticed in the <\/span><a href=\"http:\/\/blogs.technet.comhttps:\/\/devblogs.microsoft.com\/scripting\/2011-scripting-games-all-links-on-one-page\/\"><span style=\"font-family: Segoe\">2011 Scripting Games<\/span><\/a><span style=\"font-family: Segoe\"> is that some people work way too hard on their solutions. The other cool thing about Windows PowerShell is that in the end, if something runs without errors and something does what you need to be done, it is a solution. If I can write a bit of code in five minutes that is ugly but works, it is probably better than something that is elegant but takes me five hours to write. Don&rsquo;t get too hung up on trying to craft the ultimate one-liner when you have a job to do, and that job does not entail crafting the ultimate one-liner.<\/span><\/span><\/p>\n<p><span style=\"font-family: Segoe;font-size: small\">On the other hand, there is something to be said for thinking about how to do things more effectively in Windows PowerShell. GM, I am imagining that your approach was to do something like this:<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: Segoe;font-size: small\">import-csv C:\\fso\\usersconsolidated.csv | foreach { If($_.ou -match &#8220;Atlanta&#8221;) {$_.OU -replace &#8220;Atlanta&#8221;,&#8221;Cobb&#8221;}} | export-csv c:\\myfolder\\myfile.csv<\/span><\/p>\n<p><span style=\"font-family: Segoe;font-size: small\">This command does not work the way you want it to work &hellip; in fact, it does not really work very well at all because it does not produce the expected results. You are getting hung up with wrestling with the pipeline, getting confused with the <b>Foreach-Object<\/b> cmdlet (that is interrupting your pipeline), and messing about with the <b>Export-CSV<\/b> command that is not producing a CSV file at all. <\/span><\/p>\n<p><span style=\"font-family: Segoe;font-size: small\">While it is true that Windows PowerShell has some pretty cool cmdlets for working with CSV and for working with files, it is also true that at times, I want to be able to read the entire contents of a file into memory, and work on it at one time. The <b>Get-Content<\/b> cmdlet does not permit this; it basically creates an array of lines of text, which is great on most occasions. <\/span><\/p>\n<p><span style=\"font-size: small\"><span style=\"font-family: Segoe\">To easily read the contents of a file all at once, I use the <b>readalltext<\/b><i> <\/i>static method from <\/span><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.io.file.aspx\"><span style=\"font-family: Segoe\">the File<i> <\/i>class<\/span><\/a><span style=\"font-family: Segoe\"> from the .NET Framework. The <b>File<\/b><i> <\/i>class resides in the <\/span><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.io.aspx\"><span style=\"font-family: Segoe\">System.IO .NET Framework namespace<\/span><\/a><span style=\"font-family: Segoe\">. When using this class, I use square brackets around the class and namespace name. I can leave off the word <i>system <\/i>if I want to, or I can type it if I wish&mdash;it does not matter. If the word <i>system <\/i>is not present, Windows PowerShell will assume that the namespace contains the word <i>system <\/i>in it and will automatically use that when attempting to find the class. The .NET Framework namespaces are similar to the namespaces used in WMI because they are used to group related classes together for ease of reference. The difference is that the .NET Framework namespaces are a bit more granular. Therefore, if I am interested in working with files, directories, paths, file information, and other related items, I would go to the System.IO .NET Framework namespace and look around to see what is available. <\/span><\/span><\/p>\n<p><span style=\"font-size: small\"><span style=\"font-family: Segoe\">After I find the <b>File<\/b><i> <\/i>class, I can look it up on MSDN to see which methods it includes. The easiest ones to use are the static members (methods, properties, and events taken together become members) because using Windows PowerShell, all I need to do is to put the namespace\/class name combination inside square brackets, use two colons, and the name of the method. And it works. Many times, the things a class provides are available somewhere else. For example, the <b>File<\/b><i> <\/i>.NET Framework class provides a <\/span><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.io.file.exists.aspx\"><span style=\"font-family: Segoe\">static method called exists<\/span><\/a><span style=\"font-family: Segoe\"><i>. <\/i>This method returns a Boolean value (true or false) that lets me know if a file exists or not. To use this method, I provide a string to the method. This technique is shown here:<\/span><\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: Segoe;font-size: small\">PS C:\\&gt; [io.file]::exists(&#8220;C:\\fso\\UserGroupNames.txt&#8221;)<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: Segoe;font-size: small\">True<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: Segoe;font-size: small\">PS C:\\&gt; [io.file]::exists(&#8220;C:\\fso\\missingfile.xxx&#8221;)<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: Segoe;font-size: small\">False<\/span><\/p>\n<p><span style=\"font-family: Segoe;font-size: small\">I can accomplish the same thing by using the Test-Path cmdlet. This appears here.<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: Segoe;font-size: small\">PS C:\\&gt; Test-Path C:\\fso\\UserGroupNames.txt<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: Segoe;font-size: small\">True<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: Segoe;font-size: small\">PS C:\\&gt; Test-Path C:\\fso\\missingfile.xxx<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: Segoe;font-size: small\">False<\/span><\/p>\n<p><span style=\"font-family: Segoe;font-size: small\">It is always preferable to use a native Windows PowerShell cmdlet to do something, rather than resorting to .NET Framework, COM, WMI, ADSI, or some other technology&mdash;unless you have a compelling reason for doing otherwise. <\/span><\/p>\n<p><span style=\"font-size: small\"><span style=\"font-family: Segoe\">A static method called <b>readalltext<\/b><i> <\/i>is available from the <b>file<\/b><i> <\/i>class, and it can be used in two ways. The first way is to <\/span><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/ms143368.aspx\"><span style=\"font-family: Segoe\">supply a string that points to the path<\/span><\/a><span style=\"font-family: Segoe\"> to the file to open. The second way is to specify the encoding of the file. Most of the time when reading a file, the encoding is not required because the method <\/span><span style=\"font-family: Segoe\">attempts to detect automatically the encoding of a file based on the presence of byte order marks. Encoding formats UTF-8 and UTF-32 (both big endian and little endian) can be detected. The result of using the <b>readalltext<\/b><i> <\/i>method is that I get back a bunch of text in the form of a <b>String<\/b> class. <\/span><a href=\"http:\/\/msdn.microsoft.com\/en-us\/library\/system.string.aspx\"><span><span style=\"font-family: Segoe\">The String<i> <\/i>class<\/span><\/span><\/a><span style=\"font-family: Segoe\"> resides in the System .NET Framework namespace, and it contains a large number of methods. One of those methods is the <b>replace<\/b><i> <\/i>method. I therefore add the <b>replace<\/b><i> <\/i>method to the end of the <b>readalltext<\/b><i> <\/i>method. The command to read all of the text in a file (CSV file) and to replace every instance of the word <i>atlanta <\/i>with the word <i>cobb <\/i>is shown here:<\/span><\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: Segoe;font-size: small\">[io.file]::readalltext(&#8220;C:\\fso\\usersconsolidated.csv&#8221;).replace(&#8220;atlanta&#8221;,&#8221;cobb&#8221;)<\/span><\/p>\n<p><span style=\"font-family: Segoe;font-size: small\">The command to read a text file and replace words, and its associated output are shown in the following figure.<\/span><\/p>\n<p><span style=\"font-family: Segoe;font-size: small\"><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4186.hsg-11-3-11-01.png\"><img decoding=\"async\" style=\"border: 0px\" title=\"Image of command and associated output\" alt=\"Image of command and associated output\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/4186.hsg-11-3-11-01.png\" \/><\/a><\/span><\/p>\n<p><span style=\"font-family: Segoe;font-size: small\">To write this to a text file is simple. I can use the <b>Out-File<\/b> cmdlet as shown here:<\/span><\/p>\n<p style=\"padding-left: 30px\"><span style=\"font-family: Segoe;font-size: small\">[io.file]::readalltext(&#8220;C:\\fso\\usersconsolidated.csv&#8221;).replace(&#8220;Atlanta&#8221;,&#8221;Cobb&#8221;) | Out-File c:\\fso\\replacedAtlanta.csv -Encoding ascii &ndash;Force<\/span><\/p>\n<p><span style=\"font-family: Segoe;font-size: small\">The above is a single-line command that wraps in my Word document. I have not added any line continuation to the command. Keep in mind this technique is case sensitive. It will replace <i>Atlanta<\/i>, but not <i>atlanta<\/i>. The newly created text file is shown in the following figure. <\/span><\/p>\n<p><span style=\"font-family: Segoe;font-size: small\"><a href=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/7144.hsg-11-3-11-02.png\"><img decoding=\"async\" style=\"border: 0px\" title=\"Image of newly created text file\" alt=\"Image of newly created text file\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/7144.hsg-11-3-11-02.png\" width=\"464\" height=\"599\" \/><\/a><\/span><span style=\"font-family: Segoe;font-size: small\">&nbsp;<\/span><\/p>\n<p><span style=\"font-size: small\"><span style=\"font-family: Segoe\">GM, that is all there is to replacing values in a CSV file. Join me tomorrow for more exciting Windows PowerShell fun. <\/span><a href=\"http:\/\/en.wikipedia.org\/wiki\/TTFN\"><span style=\"font-family: Segoe\">TTFN<\/span><\/a><span style=\"font-family: Segoe\">.<\/span><\/span><\/p>\n<p><span style=\"font-size: small\"><span style=\"font-family: Segoe\">I invite you to follow me on <\/span><a href=\"http:\/\/bit.ly\/scriptingguystwitter\" target=\"_blank\"><span style=\"font-family: Segoe\">Twitter<\/span><\/a><span style=\"font-family: Segoe\"> and <\/span><a href=\"http:\/\/bit.ly\/scriptingguysfacebook\"><span style=\"font-family: Segoe\">Facebook<\/span><\/a><span style=\"font-family: Segoe\">. If you have any questions, send email to me at <\/span><a href=\"mailto:scripter@microsoft.com\" target=\"_blank\"><span style=\"font-family: Segoe\">scripter@microsoft.com<\/span><\/a><span style=\"font-family: Segoe\">, or post your questions on the <\/span><a href=\"http:\/\/bit.ly\/scriptingforum\" target=\"_blank\"><span style=\"font-family: Segoe\">Official Scripting Guys Forum<\/span><\/a><span style=\"font-family: Segoe\">. See you tomorrow. Until then, peace.<\/span><\/span><\/p>\n<\/p>\n<p><span style=\"font-size: small\"><b>Ed Wilson, Microsoft Scripting Guy<\/b><\/span><\/p>\n<p><span style=\"font-family: Segoe;font-size: small\"><\/span>&nbsp;<\/p>\n<p><span style=\"font-family: Segoe;font-size: small\">&nbsp;<\/span><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Summary: Learn how to search for and replace words in a CSV file by using Windows PowerShell. &nbsp; Hey, Scripting Guy! I have a comma-separated value (CSV) file that contains user names, user groups, and organizational unit (OU) assignments. The problem is that we are moving one of our office locations, and I need to [&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":[169,3,4,14,45],"class_list":["post-12201","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-csv-and-other-delimited-files","tag-scripting-guy","tag-scripting-techniques","tag-text-files","tag-windows-powershell"],"acf":[],"blog_post_summary":"<p>Summary: Learn how to search for and replace words in a CSV file by using Windows PowerShell. &nbsp; Hey, Scripting Guy! I have a comma-separated value (CSV) file that contains user names, user groups, and organizational unit (OU) assignments. The problem is that we are moving one of our office locations, and I need to [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/12201","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=12201"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/12201\/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=12201"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=12201"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=12201"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}