{"id":55223,"date":"2008-07-03T02:29:00","date_gmt":"2008-07-03T02:29:00","guid":{"rendered":"https:\/\/blogs.technet.microsoft.com\/heyscriptingguy\/2008\/07\/03\/hey-scripting-guy-how-can-i-replace-a-series-of-variables-found-in-a-text-file-with-values-taken-from-that-file\/"},"modified":"2008-07-03T02:29:00","modified_gmt":"2008-07-03T02:29:00","slug":"hey-scripting-guy-how-can-i-replace-a-series-of-variables-found-in-a-text-file-with-values-taken-from-that-file","status":"publish","type":"post","link":"https:\/\/devblogs.microsoft.com\/scripting\/hey-scripting-guy-how-can-i-replace-a-series-of-variables-found-in-a-text-file-with-values-taken-from-that-file\/","title":{"rendered":"Hey, Scripting Guy! How Can I Replace a Series of Variables Found in a Text File with Values Taken From That File?"},"content":{"rendered":"<p><img decoding=\"async\" class=\"nearGraphic\" title=\"Hey, Scripting Guy! Question\" height=\"34\" alt=\"Hey, Scripting Guy! Question\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/q-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\" \/> <\/p>\n<p>Hey, Scripting Guy! I have a text file containing TSQL syntax. In this file are a number of variables: @P1, @P2, @p3, and so on, up through @P58. The bottom line of the text file contains replacement values for these variables; for example, I need to take the variable @P1 and replace it with the first value in the last line; I need to replace @P2 with the second value in the last line; etc. How can I do that?<\/p>\n<p>&#8212; AG<\/p>\n<p><img decoding=\"async\" height=\"5\" alt=\"Spacer\" src=\"https:\/\/devblogs.microsoft.com\/scripting\/wp-content\/uploads\/sites\/29\/2019\/05\/spacer.gif\" width=\"5\" border=\"0\" \/><img decoding=\"async\" class=\"nearGraphic\" title=\"Hey, Scripting Guy! Answer\" height=\"34\" alt=\"Hey, Scripting Guy! Answer\" src=\"https:\/\/devblogs.microsoft.com\/wp-content\/uploads\/sites\/29\/2019\/02\/a-for-powertip.jpg\" width=\"34\" align=\"left\" border=\"0\" \/><a href=\"http:\/\/go.microsoft.com\/fwlink\/?linkid=68779&amp;clcid=0x409\"><img decoding=\"async\" class=\"farGraphic\" title=\"Script Center\" height=\"288\" alt=\"Script Center\" src=\"http:\/\/img.microsoft.com\/library\/media\/1033\/technet\/images\/scriptcenter\/ad.jpg\" width=\"120\" align=\"right\" border=\"0\" \/><\/a> <\/p>\n<p>Hey, AG. You know what you need here? You need some \u201cconcentrated water.\u201d That\u2019s right: concentrated water. Apparently concentrated water has been around for a few years now although, as usual, the Scripting Guy who writes this column is a bit late to the party. (Actually, the Scripting Guy who writes this column never even gets <i>invited<\/i> to the party, but that\u2019s another story.) Concentrated water: because who would drink water that <i>hasn\u2019t<\/i> been restructured through a system of centrifugal vortex and magnetic resonance?<\/p>\n<p>Good question: what exactly <i>is<\/i> concentrated water? To tell you the truth, we weren\u2019t sure. Therefore, we did a Goo \u2013 um, an <i>Internet<\/i> search and managed to find the following explanation. It turns out that concentrated water:<\/p>\n<p>\u201c\u2026 contains the energetic properties needed to optimize the body&#8217;s hydration and detoxification capabilities. Its proprietary nature-based technology is a unique energetic process that duplicates the flow dynamics, polarity, vibrational strength and subtle energetic qualities produced by nature under ideal spring water conditions. It contains the full range of frequencies found in the human energy field, along with a naturally strong polarity, which combine to tune and raise the vibrations of the body&#8217;s energy field every time you drink Hydra water.\u201d<\/p>\n<p>Needless to say, that cleared things up.<\/p>\n<p>Anyway, the cool thing about concentrated water is this: although you <i>can<\/i> drink it straight from the bottle ($9.95 for a 14-ounce bottle), the recommended way to use concentrated water is to dilute it. And how do you dilute it? Why, by adding water to it, of course. In other words, concentrated water is water that you need to add water to.<\/p>\n<p>Good point: why <i>didn\u2019t\u2019<\/i> the Scripting Guys think of that? <\/p>\n<p>But that\u2019s neither here nor there; the important question is whether or not concentrated water would be of any use in replacing values in a text file? To try and answer that question, let\u2019s first take a look at the text file (which we\u2019ve simplified a bit). The file looks something like&nbsp;this:<\/p>\n<pre class=\"codeSample\">select pilot.dbo.CUSTOMERS.CUSTNAME , case when ( ( coalesce( pilot.dbo.NSCUST.CUSTDES , '''' ) = \nrtrim(ltrim(reverse( @P1 ))) ) ) then ( pilot.dbo.CUSTOMERS.CUSTDES ) else \n( coalesce( pilot.dbo.NSCUST.CUSTDES , '''' ) ) end , pilot.dbo.ORDERS.CURDATE , pilot.dbo.ORDERS.ORDNAME , \npilot.dbo.ORDERS.BOOKNUM , pilot.dbo.DOCUMENTS.DOCNO , pilot.dbo.ORDSTATUS.ORDSTATUSDES , \npilot.dbo.ORDSTATUS.XVR_GRADING , case when ( ( pilot.dbo.ORDERS.CLOSED = @P2 ) ) then ( @P3 ) else ( @P4 ) \nend , case when ( ( pilot.dbo.ORDERS.PCLOSED = @P5 ) ) then (@P6 ) else ( @P7 ) end , pilot.dbo.CPROF.CPROFNUM , \npilot.dbo.DEAL.ORDNAME \n\n'','C','Y',' ','C','Y',' '\n<\/pre>\n<p>What AG needs to do is take the comma-separated values on the last line and use those as replacements for the variable values (anything starting with <b>@P<\/b>) in the main body of his text file. For example, part of AG\u2019s TSQL text looks like this:<\/p>\n<pre class=\"codeSample\">rtrim(ltrim(reverse( @P1 )<\/pre>\n<p>What he wants to do is replace @P1 with the first value in the last line of the text file (<b>\u2018 \u2018<\/b>). In other words, his new-and-improved TSQL syntax needs to look like this:<\/p>\n<pre class=\"codeSample\">rtrim(ltrim(reverse( '' )<\/pre>\n<p>See how that works?<\/p>\n<p>Now, it may very well be the case that AG could solve his problem by dunking his computer in a bucket of concentrated water; needless to say, a <i>lot<\/i> of life\u2019s problems could be solved by dunking your computer in a bucket of concentrated water (or by throwing that computer out the window). However, we can\u2019t be sure about that, and we don\u2019t really recommend you try it. (At the very least, don\u2019t dunk your own computer in a bucket of water; try using someone else\u2019s computer first.) Because of that, we recommend that you use the following script insteadinstead:<\/p>\n<pre class=\"codeSample\">Const ForReading = 1\nConst ForWriting = 2\n\nSet objFSO = CreateObject(\"Scripting.FileSystemObject\")\nSet objFile = objFSO.OpenTextFile(\"C:\\Scripts\\Test.txt\", ForReading)\n\nstrContents = objFile.ReadAll\nobjFile.Close\n\narrContents = Split(strContents, vbCrlf)\nintUpper = Ubound(arrContents)\narrReplacements = Split(arrContents(intUpper), \",\")\n\ni = 1\n\nFor Each strReplacement in arrReplacements\n    strTarget = \"@P\" &amp; i\n    strContents = Replace(strContents, strTarget, strReplacement)\n    i = i + 1\nNext\n\nSet objFile = objFSO.OpenTextFile(\"C:\\Scripts\\Test.txt\", ForWriting)\nobjFile.WriteLine strContents\nobjFile.Close\n<\/pre>\n<p>OK, let\u2019s see what we have here. To begin with, we define a pair of constants (ForReading and ForWriting), constants that we\u2019ll need to open our text file. (Why do we need <i>two<\/i> constants? Because we\u2019re going to have to open the text file two times: once to read from it, and once to write to it.) After defining the constants we create an instance of the <b>Scripting.FileSystemObject<\/b>, then use the <b>OpenTextFile<\/b> method to open the file&nbsp;C:\\Scripts\\Test.txt:<\/p>\n<pre class=\"codeSample\">Set objFSO = CreateObject(\"Scripting.FileSystemObject\")\nSet objFile = objFSO.OpenTextFile(\"C:\\Scripts\\Test.txt\", ForReading)\n<\/pre>\n<p>Just a second here; our vibrational frequencies seem to be a little out-of-whack.<\/p>\n<p>There, that\u2019s better. So what are we going to do with this file now that it\u2019s open? That\u2019s easy: we\u2019re going to use the <b>ReadAll<\/b> method to read the entire contents of the file into a variable named strContents, then we\u2019re going to immediately close the file.<\/p>\n<table class=\"dataTable\" id=\"E4E\" cellSpacing=\"0\" cellPadding=\"0\">\n<thead><\/thead>\n<tbody>\n<tr class=\"record\" vAlign=\"top\">\n<td class=\"\">\n<p><b>Note<\/b>. What\u2019s the point of opening the file and then immediately closing it again? Well, ideally, we\u2019d be able to open the file and modify the contents as we go. For better or worse, however, the FileSystemObject won\u2019t let us do that. Instead, we need to open the file, read in the contents, and then close the file; we then modify the \u201cvirtual\u201d contents of the file in memory. As soon as our changes are complete we reopen the file, this time for writing, and replace the existing contents with our new, modified contents.<\/p>\n<p>And no, we aren\u2019t sure why the FileSystemObject works that way. We\u2019re assuming it has something to do with the inverse hydrochloric polarity of the vibrational calculometer built into the FileSystemObject. But we could be mistaken about that.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>As it turns out, the FileSystemObject (as much as we love it) has at least one more eccentricity: there\u2019s no straightforward way to read the last line \u2013 and only the last line \u2013 in a file. Most of the time that\u2019s no problem. In this case, however, it <i>is<\/i> a problem: after all, AG\u2019s replacement values are all found in the last line of the text file. So what are we going to do about that? Well, we\u2019re going to execute this block of&nbsp;code:<\/p>\n<pre class=\"codeSample\">arrContents = Split(strContents, vbCrlf)\nintUpper = Ubound(arrContents)\narrReplacements = Split(arrContents(intUpper), \",\")\n<\/pre>\n<p>So how does this chunk of code let us read the last line in the file? Well, to begin with, we use the <b>Split<\/b> function to split the contents of the file into an array named arrContents; by splitting this value on the carriage return-linefeed character (<b>vbCrLf<\/b>) we end up creating an array in which each and every element in that array happens to be a line in the text file. As soon as we\u2019ve created this array, we can then use the <b>Ubound<\/b> function to determine the index number of the very last item in that array (which, needless to say, is also the last line in the text file).<\/p>\n<p>So then what\u2019s <i>this<\/i> line of code for?<\/p>\n<pre class=\"codeSample\">arrReplacements = Split(arrContents(intUpper), \",\")<\/pre>\n<p>Well, as you recall, the last line in the text file is a set of replacement values; that last line looks like this:<\/p>\n<pre class=\"codeSample\">'','C','Y',' ','C','Y',' '<\/pre>\n<p>All we\u2019re doing here is using the Split function to create another array, this one composed of the individual items found in the last line of the file. By splitting on the comma, we end up with an array named arrReplacements that looks like:<\/p>\n<pre class=\"codeSample\">''\n'C'\n'Y'\n' '\n'C'\n'Y'\n' '\n<\/pre>\n<p class=\"lastInCell\"><b>Note<\/b>. In case you\u2019re wondering, yes, we do need to keep the single quote marks.<\/p>\n<p>&nbsp;<\/p>\n<p>Believe it or not, we\u2019re now ready to start replacing variables with values (or at least we will be after we set the value of a counter variable named i to 1). To carry out this task, the first thing we do is set up a For Each loop that will loop us through all the values in the variable arrReplacements. Inside that loop, the first thing we do is execute this line of code:<\/p>\n<pre class=\"codeSample\">strTarget = \"@P\" &amp; i<\/pre>\n<p>What we\u2019re doing here is simply constructing the target text that needs to be replaced. As AG noted in his email, his text file contains a series of variables that look like this: @P1; @P2; @P3; etc. With this line of code we\u2019re simply constructing the first of these variables, combining the string value <b>@P<\/b> with the value of the counter variable i. Because i is currently equal to 1, that\u2019s going to make our target text equal to this: <b>@P1<\/b>. See how that works?<\/p>\n<p>As soon as we\u2019ve done that we can then use the <b>Replace<\/b> function to search our text file (or, more correctly, the virtual copy of the text file stored in the variable strContents) for the target text, and the replace that value with the first value in the array arrReplacements. That\u2019s what this line of code is for:<\/p>\n<pre class=\"codeSample\">strContents = Replace(strContents, strTarget, strReplacement)<\/pre>\n<p>From there we increment the value of the counter variable i by 1, then go back to the top of the loop and try again, this time replaced the variable @P2 with the second value found in the array arrReplacements.<\/p>\n<p>Etc., etc.<\/p>\n<p>After all the replacements have been made we reopen Test.txt (this time for writing), then use the <b>WriteLine<\/b> method to replace the existing contents of the file with the value of the variable strContents:<\/p>\n<pre class=\"codeSample\">objFile.WriteLine strContents<\/pre>\n<p>We then close the file, and call it good.<\/p>\n<table class=\"dataTable\" id=\"EIH\" cellSpacing=\"0\" cellPadding=\"0\">\n<thead><\/thead>\n<tbody>\n<tr class=\"record\" vAlign=\"top\">\n<td class=\"\">\n<p class=\"lastInCell\"><b>Note<\/b>. We should point out that Test.txt will still contain the last line from the original file, the set of replacement values. That\u2019s still there for one reason and one reason only: AG didn\u2019t say he needed it removed. However, we <i>could<\/i> easily remove it by re-converting strContents to an array, then saving everything except the last line (or the last two lines, or the last three lines, or \u2026.). For more information on how you might go about doing that, take a peek at <a href=\"http:\/\/www.microsoft.com\/technet\/scriptcenter\/resources\/qanda\/sept06\/hey0911.mspx\"><b>this<\/b><\/a><i>Hey, Scripting Guy!<\/i> column.<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<div class=\"dataTableBottomMargin\"><\/div>\n<p>Incidentally, here\u2019s what the data section of Test.txt will now look&nbsp;like:<\/p>\n<pre class=\"codeSample\">select pilot.dbo.CUSTOMERS.CUSTNAME , case when ( ( coalesce( pilot.dbo.NSCUST.CUSTDES , '''' ) \n= rtrim(ltrim(reverse( '' ))) ) ) then ( pilot.dbo.CUSTOMERS.CUSTDES ) else \n( coalesce( pilot.dbo.NSCUST.CUSTDES , '''' ) ) end , pilot.dbo.ORDERS.CURDATE , pilot.dbo.ORDERS.ORDNAME , \npilot.dbo.ORDERS.BOOKNUM , pilot.dbo.DOCUMENTS.DOCNO , pilot.dbo.ORDSTATUS.ORDSTATUSDES , \npilot.dbo.ORDSTATUS.XVR_GRADING , case when ( ( pilot.dbo.ORDERS.CLOSED = 'C' ) ) then ( 'Y' ) else ( ' ' ) \nend , case when ( ( pilot.dbo.ORDERS.PCLOSED = 'C' ) ) then ('Y' ) else ( ' ' ) end , pilot.dbo.CPROF.CPROFNUM , \npilot.dbo.DEAL.ORDNAME\n<\/pre>\n<p>Not bad, huh?<\/p>\n<p>That should do it, AG; as always, it turns out that the best way to get something done is to go ahead and do it yourself. So does that apply to making your own concentrated water as well? You bet it does. After all, why pay $9.95 for a 14-ounce bottle of concentrated water when you can make your own? All you have to do is take regular tap water and restore the super high exahertz and nanotesla range frequencies. Season with salt and pepper, and then stir well.<\/p>\n<table class=\"dataTable\" id=\"EDAAC\" cellSpacing=\"0\" cellPadding=\"0\">\n<thead><\/thead>\n<tbody>\n<tr class=\"record\" vAlign=\"top\">\n<td class=\"\">\n<p class=\"lastInCell\"><b>Note<\/b>. In case you\u2019re wondering, concentrated water is not the most expensive bottled water in the world; as near as we can tell, that honor goes to Bling H20, on sale now for $20 for a 12-ounce bottle of plain water, $40 if you want the Creamy Mint flavor. (And no, we\u2019re not making that up: Creamy Mint is, apparently, an actual water flavor.)<\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n","protected":false},"excerpt":{"rendered":"<p>Hey, Scripting Guy! I have a text file containing TSQL syntax. In this file are a number of variables: @P1, @P2, @p3, and so on, up through @P58. The bottom line of the text file contains replacement values for these variables; for example, I need to take the variable @P1 and replace it with the [&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":[169,3,4,14,5],"class_list":["post-55223","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-vbscript"],"acf":[],"blog_post_summary":"<p>Hey, Scripting Guy! I have a text file containing TSQL syntax. In this file are a number of variables: @P1, @P2, @p3, and so on, up through @P58. The bottom line of the text file contains replacement values for these variables; for example, I need to take the variable @P1 and replace it with the [&hellip;]<\/p>\n","_links":{"self":[{"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/55223","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=55223"}],"version-history":[{"count":0,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/posts\/55223\/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=55223"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/categories?post=55223"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/devblogs.microsoft.com\/scripting\/wp-json\/wp\/v2\/tags?post=55223"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}