{"id":71203,"date":"2004-10-18T08:52:00","date_gmt":"2004-10-18T08:52:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2004\/10\/18\/how-can-i-pick-out-and-save-specific-lines-in-a-text-file\/"},"modified":"2004-10-18T08:52:00","modified_gmt":"2004-10-18T08:52:00","slug":"how-can-i-pick-out-and-save-specific-lines-in-a-text-file","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/how-can-i-pick-out-and-save-specific-lines-in-a-text-file\/","title":{"rendered":"How Can I Pick Out and Save Specific Lines in a Text File?"},"content":{"rendered":"<p><IMG class=\"nearGraphic\" 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\"> \n<P>Hey, Scripting Guy! I\u2019d like to be able to read through a text file, select the lines that begin with a particular word (like <B>Failure<\/B>), and then save <I>only<\/I> those lines back to the same text file. Is there any way to do that?<BR><BR>&#8212; AC<\/P><IMG border=\"0\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" height=\"5\"><IMG class=\"nearGraphic\" 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\"><A href=\"http:\/\/go.microsoft.com\/fwlink\/?linkid=68779&amp;clcid=0x409\"><IMG class=\"farGraphic\" title=\"Script Center\" border=\"0\" alt=\"Script Center\" align=\"right\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/ad.jpg\" width=\"120\" height=\"288\"><\/A> \n<P>Hey, AC. Hey, AC. For simplicity\u2019s sake, we\u2019re assuming you have a text file that looks similar to this:<\/P><PRE class=\"codeSample\">Success &#8211; Operation succeeded 10\/1\/2004.\nSuccess &#8211; Operation succeeded 10\/2\/2004.\nFailure &#8211; Operation failed 10\/3\/2004.\nSuccess &#8211; Operation succeeded 10\/4\/2004.\nFailure &#8211; Operation failed 10\/5\/2004.\nSuccess &#8211; Operation succeeded 10\/6\/2004.\nFailure &#8211; Operation failed 10\/7\/2004.\nFailure &#8211; Operation failed 10\/8\/2004.\n<\/PRE>\n<P>You\u2019d like to have a script read through the file, toss out all the lines that begin with <B>Success<\/B>, and then save the file, a file which will then hold only information about the operations that failed. In other words, you want the revised file to look like this:<\/P><PRE class=\"codeSample\">Failure &#8211; Operation failed 10\/3\/2004.\nFailure &#8211; Operation failed 10\/5\/2004.\nFailure &#8211; Operation failed 10\/7\/2004.\nFailure &#8211; Operation failed 10\/8\/2004.\n<\/PRE>\n<P>Can you do this with a script? Of course you can:<\/P><PRE class=\"codeSample\">Const ForReading = 1\nConst ForWriting = 2<\/p>\n<p>Set objFSO = CreateObject(&#8220;Scripting.FileSystemObject&#8221;)\nSet objTextFile = objFSO.OpenTextFile _\n    (&#8220;test.log&#8221;, ForReading)<\/p>\n<p>Do Until objTextFile.AtEndOfStream\n    strLine = objTextFile.ReadLine\n    If Left(strLine, 7) = &#8220;Failure&#8221; Then\n        strNewText = strNewText &amp; strLine &amp; vbCrLf\n    End If\nLoop<\/p>\n<p>objTextFile.Close\nSet objTextFile = objFSO.OpenTextFile _\n    (&#8220;test.log&#8221;, ForWriting)\nobjTextFile.Write(strNewText)\nobjTextFile.Close\n<\/PRE>\n<P>This script looks a tad bit complicated, but that\u2019s because there\u2019s no way to directly edit a text file using a script. Instead, we have to open the text file, read in the current contents, and then close the file. We then do our \u201cediting\u201d in memory, re-open the text file, replace the current contents with our new data, and then close the file again. And that\u2019s exactly what this script does.<\/P>\n<P>After defining a couple of constants (ForReading and ForWriting, constants we\u2019ll need to open the text file), the script opens the file test.log for reading. We then create a Do loop that runs until we reach the end of the text file; in other words, until we are at the end of the text stream.<\/P>\n<P>And what happens inside that loop? We begin by using the ReadLine method to read the current line of the text file; that line of text gets stored in the variable strLine. We then check to see if the first 7 characters of the line happen to be <B>Failure<\/B>; that\u2019s what the command <B>If Left(strLine, 7) = \u201cFailure\u201d<\/B> does. If the first seven characters are anything <I>but<\/I><B>Failure<\/B>, then we simply loop back around and read the next line in the file.<\/P>\n<P>But what if the first seven characters <I>are<\/I><B>Failure<\/B>? In that case, we have another variable &#8211; strNewText &#8211; that we use to store the data we want to save. The line of code <B>strNewText = strNewText &amp; strLine &amp; vbCrLf<\/B> just takes whatever happens to be in strNewText at the moment, append the value of strLine, and then add a carriage return-linefeed to the end (vbCrLf). This builds up a new dataset in memory; by the time we finish reading the entire file, strNewText is equal to this:<\/P><PRE class=\"codeSample\">Failure &#8211; Operation failed 10\/3\/2004.\nFailure &#8211; Operation failed 10\/5\/2004.\nFailure &#8211; Operation failed 10\/7\/2004.\nFailure &#8211; Operation failed 10\/8\/2004.\n<\/PRE>\n<P>In other words, all we\u2019ve done is read the file and keep a list of all the lines beginning with the word <B>Failure<\/B>; any lines beginning with anything else have been ignored.<\/P>\n<P>Now that we have our new dataset, we need to close the text file and then reopen it, this time using the constant ForWriting. (Yes, we know, but that\u2019s the way the FileSystemObject works: you have to open it for reading, then close it and reopen it for writing.) With the file open we use the Write method to replace the existing contents of test.log with the value of our variable strNewText. We then close the file, which saves the change we just made. The net effect? Test.log now contains <I>only<\/I> a list of operations that failed:<\/P><PRE class=\"codeSample\">Failure &#8211; Operation failed 10\/3\/2004.\nFailure &#8211; Operation failed 10\/5\/2004.\nFailure &#8211; Operation failed 10\/7\/2004.\nFailure &#8211; Operation failed 10\/8\/2004.\n<\/PRE>\n<P>A tiny bit cumbersome, but it works just fine.<\/P>\n<P>Of course, often times the word you are looking for isn\u2019t found at the beginning of the line, but is instead found somewhere in the middle of the line. For example, your log file might look like this:<\/P><PRE class=\"codeSample\">10\/1\/2004     Success &#8211; Operation succeeded.\n10\/2\/2004     Success &#8211; Operation succeeded.\n10\/3\/2004     Failure &#8211; Operation failed.\n10\/4\/2004     Success &#8211; Operation succeeded.\n10\/5\/2004     Failure &#8211; Operation failed.\n10\/6\/2004     Success &#8211; Operation succeeded.\n10\/7\/2004     Failure &#8211; Operation failed.\n10\/8\/2004     Failure &#8211; Operation failed.\n<\/PRE>\n<P>If that\u2019s the case, then checking to see the value of the first 7 characters in each line won\u2019t do you much good; you need to check to see if the word <B>Failure<\/B> appears <I>anywhere<\/I> within the line. But that\u2019s all right; you can just use the VBScript function InStr. With InStr you pass it two parameters: the string to search (the variable strLine) and the item to search for the word <B>Failure<\/B>). InStr will respond by telling you the character position at which the word <B>Failure<\/B> begins. For example, in this line the word <B>Failure<\/B> begins at character 15, so InStr returns a 15:<\/P><PRE class=\"codeSample\">10\/5\/2004     Failure &#8211; Operation failed.\n<\/PRE>\n<P>If the search term can\u2019t be found in the string, then IntStr returns a 0. Therefore, we just use InStr to search each line for the word <B>Failure<\/B>. If InStr is greater than 0, that means the word was found, and we add the line to the variable strNewText. Here\u2019s a revised Do loop that searches for the value <B>Failure<\/B> anywhere within the line:<\/P><PRE class=\"codeSample\">Do Until objTextFile.AtEndOfStream\n    strLine = objTextFile.ReadLine\n    intFailure = InStr(strLine, &#8220;Failure&#8221;)\n    If intFailure &gt; 0 Then\n        strNewText = strNewText &amp; strLine &amp; vbCrLf\n    End If\nLoop\n<\/PRE>\n<P>Could we have used this approach earlier? Sure. But when we know sure that the term we\u2019re looking for will be found at the beginning of the line, we think Left is a better choice (and the Right function is best if we know for sure that the term in question appears at the end of the line). That\u2019s because it\u2019s at least theoretically possible to \u201cfool\u201d the InStr function. For example, InStr will peg this line as marking a failure, even though it actually represents a successful operation:<\/P><PRE class=\"codeSample\">Success &#8211; Failure troubleshooter successfully loaded 10\/1\/2004.\n<\/PRE>\n<P>A somewhat unlikely occurrence, sure. But why take any chances?<\/P>\n<P>P.S. We know we\u2019ll get a bunch of letters from people saying, \u201cWhat about regular expressions?\u201d Yes, regular expressions are very powerful, but they\u2019re also a bit too complex to explain in this column. We\u2019ll take up regular expressions sometime soon, but somewhere other than the <I>Hey, Scripting Guy!<\/I> column.<\/P><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! I\u2019d like to be able to read through a text file, select the lines that begin with a particular word (like Failure), and then save only those lines back to the same text file. Is there any way to do that?&#8212; AC Hey, AC. Hey, AC. For simplicity\u2019s sake, we\u2019re assuming you [&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":[3,4,21,14,5],"class_list":["post-71203","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-scripting","tag-scripting-guy","tag-scripting-techniques","tag-string-manipulation","tag-text-files","tag-vbscript"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! I\u2019d like to be able to read through a text file, select the lines that begin with a particular word (like Failure), and then save only those lines back to the same text file. Is there any way to do that?&#8212; AC Hey, AC. Hey, AC. For simplicity\u2019s sake, we\u2019re assuming you [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/71203","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=71203"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/71203\/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=71203"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=71203"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=71203"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}