0

I have built a batch file that runs a BTEQ script and returns the data in a txt file. However, I am expanding my code to allow for user input of user_id, password, and a period parameter YYYYMM. I initially wrote hard coded my personal login information into the BTEQ file and tested with just the snapshot parameter like so.

echo off
SETLOCAL ENABLEEXTENSIONS DISABLEDELAYEDEXPANSION
SET /P SNAPSHOT="What snapshot should I use [YYYYMM]?"
DEL EXPORT.TXT
POWERSHELL -COMMAND "(GET-CONTENT TEST.TXT) | FOREACH-OBJECT {$_ -REPLACE \"\?YYYYMM\"", %SNAPSHOT% "} | OUT-FILE TEST.TXT";
bteq < test.txt > output.txt 2>&1
POWERSHELL -COMMAND "(GET-CONTENT TEST.TXT) | FOREACH-OBJECT {$_ -REPLACE " %SNAPSHOT% ,"\"?YYYYMM\"} | OUT-FILE TEST.TXT";
@echo off goto end
en @echo exit

The code worked as intended. However, when I go to add the userid and password, I simply copy the snapshot code for PowerShell and replaced the variables as needed.

echo off
SETLOCAL ENABLEEXTENSIONS DISABLEDELAYEDEXPANSION
SET /P USER_ID=Enter User ID:
SET /P USER_PASSWORD=Enter Password:
SET /P SNAPSHOT="What snapshot should I use [YYYYMM]?"
DEL EXPORT.TXT
POWERSHELL -COMMAND "(GET-CONTENT TEST.TXT) | FOREACH-OBJECT {$_ -REPLACE \"$USER_ID\"", %USER_ID% "} | OUT-FILE TEST.TXT";
POWERSHELL -COMMAND "(GET-CONTENT TEST.TXT) | FOREACH-OBJECT {$_ -REPLACE \"\$USERPASSWORD\"", %USER_PASSWORD% "} | OUT-FILE TEST.TXT"; 
POWERSHELL -COMMAND "(GET-CONTENT TEST.TXT) | FOREACH-OBJECT {$_ -REPLACE \"\?YYYYMM\"", %SNAPSHOT% "} | OUT-FILE TEST.TXT";
bteq < test.txt > output.txt 2>&1
::POWERSHELL -COMMAND "(GET-CONTENT TEST.TXT) | FOREACH-OBJECT {$_ -REPLACE " %SNAPSHOT% ,"\"?YYYYMM\"} | OUT-FILE TEST.TXT";
@echo off goto end
en @echo exit

The snapshot code still works but I get errors for the User_ID and User_Password user inputs. As follows:

Enter User ID:userTest
Enter Password:TestPass
What snapshot should I use [YYYYMM]?202102

At line:1 char:66
+ ... -CONTENT TEST.TXT) | FOREACH-OBJECT {$_ -REPLACE "\$USER_ID", userTes ...
+                                                                  ~
Missing expression after ','.
At line:1 char:67
+ ... TEST.TXT) | FOREACH-OBJECT {$_ -REPLACE "\$USER_ID", userTest } | OUT ...
+                                                          ~~~~~~~~
Unexpected token 'userTest' in expression or statement.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : MissingExpressionAfterToken

At line:1 char:71
+ ... ENT TEST.TXT) | FOREACH-OBJECT {$_ -REPLACE "\$USERPASSWORD", TestPas ...
+                                                                  ~
Missing expression after ','.
At line:1 char:72
+ ... TXT) | FOREACH-OBJECT {$_ -REPLACE "\$USERPASSWORD", TestPass } | OUT ...
+                                                          ~~~~~~~~
Unexpected token 'TestPass' in expression or statement.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : MissingExpressionAfterToken
9
  • I do not believe that $_ -REPLACE \"\?YYYYMM\"", %SNAPSHOT% ", or $_ -REPLACE " %SNAPSHOT% ,"\"?YYYYMM\" are correct syntax, to begin with, (regardless of your statement that it worked as intended). You should be using this syntax, PowerShell -NoProfile -Command "(Get-Content -Path \".\test.txt\") | ForEach-Object {$_ -Replace \"StringBefore\",\"%StringAfter\"} | Set-Content -Path \".\test.txt\"". I've changed your Out-File to Set-Content, and doublequoted .\test.txt, just to highlight the correct escape syntax, (you could, if you wish change those). Commented Apr 7, 2021 at 15:35
  • Your syntax does not work at all. The %StringAfter must be %StringAfter% because of Batch. In a way it must be written like dynamic SQL with variables. Your syntax just appears to be extra steps. Why "NoProfile" before command? Commented Apr 7, 2021 at 15:40
  • 2
    %StringAfter is just a placeholder, not a variable, just change it to your string, or batch created variable as needed. The syntax is very simple, everything you are passing to powershell as -Command is enclosed in a single set of doublequotes, every doublequote inside those must be escaped with a backwards slash. That is the correct syntax, it has always worked for me on every system I've tried it on. If you want to know what -NoProfile does look it up, I'm not Alexa, Cortana, Google, or Siri Commented Apr 7, 2021 at 15:48
  • 2
    Why make your life so hard with mixture of BAT and PS instead of using only PS? Commented Apr 7, 2021 at 16:37
  • 1
    You think your Powershell code was shorter then doing it in pure batch? I bet I can do it in less characters in pure batch then your call to powershell. Commented Apr 7, 2021 at 17:16

1 Answer 1

1

Here is my suggestion, using the syntax as suggested in my comments, but instead of multiple instances of PowerShell, a single one:

%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -Command "(Get-Content -Path \".\test.txt\") | ForEach-Object { $_.Replace(\"`$USER_ID\", \"%USER_ID%\").Replace(\"`$USERPASSWORD\", \"%USER_PASSWORD%\").Replace(\"?YYYYMM\", \"%SNAPSHOT%\") } | Set-Content -Path \".\test.txt\""

If you prefer to use single quotes in PowerShell, (which in this case would be simpler to read and understand), then:

%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -Command "(Get-Content -Path '.\test.txt') | ForEach-Object { $_.Replace('$USER_ID', '%USER_ID%').Replace('$USERPASSWORD', '%USER_PASSWORD%').Replace('?YYYYMM', '%SNAPSHOT%') } | Set-Content -Path '.\test.txt'"

These examples are based upon my interpretation of what your code is supposed to replace in test.txt, i.e. the literal strings, $USER_ID, $USERPASSWORD and ?YYYYMM.

To return the string value of %SNAPSHOT% back to the literal string ?YYYYMM, after having ran your bteq command, (as you have in your code), then you could use either:

%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -Command "(Get-Content -Path \".\test.txt\") | ForEach-Object { $_.Replace(\"%SNAPSHOT%\", \"?YYYYMM\") } | Set-Content -Path \".\test.txt\""

Or

%SystemRoot%\System32\WindowsPowerShell\v1.0\powershell.exe -NoProfile -Command "(Get-Content -Path '.\test.txt') | ForEach-Object { $_.Replace('%SNAPSHOT%', '?YYYYMM') } | Set-Content -Path '.\test.txt'"

If you are returning all three strings, not just one, then you could just use your chosen the first example, and switch the places of each string pair. However, for that, I seems simpler to me, to just Set-Conent to a new file, use that, then delete, than to keep modifying the same file.

Sign up to request clarification or add additional context in comments.

2 Comments

I ran with this version of code ` POWERSHELL -Command "(Get-Content -Path '.\test.txt') | ForEach-Object { $_.Replace('$USER_ID', '%USER_ID%').Replace('$USERPASSWORD', '%USER_PASSWORD%').Replace('?YYYYMM', '%SNAPSHOT%') } | Set-Content -Path '.\test.txt' ` thanks!
You obviously didn't bother trying to find out what -NoProfile does, then… BTW, a shortened version, using aliases and assuming locations and extensions are properly configured in the running system: PowerShell -NoP "(GC 'test.txt')|%%{$_.Replace('$USER_ID','%USER_ID%').Replace('$USERPASSWORD','%USER_PASSWORD%').Replace('?YYYYMM','%SNAPSHOT%')}|SC 'test.txt'".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.