【问题标题】:Replace multiple strings in txt file using Batch and Powershell使用 Batch 和 Powershell 替换 txt 文件中的多个字符串
【发布时间】:2023-03-28 06:58:01
【问题描述】:

我已经构建了一个批处理文件,它运行 BTEQ 脚本并以 txt 文件的形式返回数据。但是,我正在扩展我的代码以允许用户输入 user_id、密码和句点参数 YYYYMM。 我最初将我的个人登录信息硬编码到 BTEQ 文件中,并像这样仅使用快照参数进行测试。

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

代码按预期工作。但是,当我去添加用户名和密码时,我只是复制了 PowerShell 的快照代码并根据需要替换了变量。

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

快照代码仍然有效,但我收到 User_ID 和 User_Password 用户输入错误。如下:

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

【问题讨论】:

  • 我不认为$_ -REPLACE \"\?YYYYMM\"", %SNAPSHOT% "$_ -REPLACE " %SNAPSHOT% ,"\"?YYYYMM\" 是正确的语法,首先,(无论您声明它是否按预期工作)。您应该使用这种语法PowerShell -NoProfile -Command "(Get-Content -Path \".\test.txt\") | ForEach-Object {$_ -Replace \"StringBefore\",\"%StringAfter\"} | Set-Content -Path \".\test.txt\""。我已将您的 Out-File 更改为 Set-Content,并双引号 .\test.txt,只是为了突出显示正确的转义语法,(如果您愿意,可以更改)
  • 您的语法根本不起作用。由于批处理,%StringAfter 必须是 %StringAfter%。在某种程度上,它必须像带有变量的动态 SQL 一样编写。您的语法似乎是额外的步骤。为什么在命令前使用“NoProfile”?
  • %StringAfter 只是一个占位符,而不是变量,只需将其更改为您的字符串,或根据需要批量创建变量。语法非常简单,您传递给powershell 的所有内容都包含在一组双引号中,其中的每个双引号都必须用反斜杠转义。这是正确的语法,它在我尝试过的每个系统上都对我有用。如果你想知道 -NoProfile 会查到什么,我不是 Alexa、Cortana、Google 或 Siri
  • 为什么要混合使用 BAT 和 PS 而不是只使用 PS 让你的生活如此艰难?
  • 您认为您的 Powershell 代码比纯批处理更短?我敢打赌,我可以在纯批处理中用更少的字符来完成,然后你对 powershell 的调用。

标签: powershell batch-file find-replace


【解决方案1】:

这是我的建议,使用我的 cmets 中建议的语法,但不是多个 PowerShell 实例,而是一个:

%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\""

如果您更喜欢在PowerShell 中使用单引号,(在这种情况下会更容易阅读和理解),那么:

%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'"

这些示例基于我对您的代码应该在test.txt 中替换的内容的解释,即文字字符串$USER_ID$USERPASSWORD?YYYYMM

要在运行bteq 命令后将%SNAPSHOT% 的字符串值返回到文字字符串?YYYYMM(正如您在代码中所做的那样),那么您可以使用要么:

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

或者

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

如果您要返回所有三个字符串,而不仅仅是一个,那么您可以使用您选择的第一个示例,并切换每个字符串对的位置。但是,为此,我似乎更简单,只需 Set-Conent 到一个新文件,使用它,然后删除,而不是继续修改同一个文件。

【讨论】:

  • 我用这个版本的代码运行 `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' ` 谢谢!
  • 你显然没有费心去找出 -NoProfile 做了什么,然后……顺便说一句,一个缩短的版本,使用别名并假设在运行的系统中正确配置了位置和扩展名:PowerShell -NoP "(GC 'test.txt')|%%{$_.Replace('$USER_ID','%USER_ID%').Replace('$USERPASSWORD','%USER_PASSWORD%').Replace('?YYYYMM','%SNAPSHOT%')}|SC 'test.txt'" .
猜你喜欢
  • 2015-11-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-03-25
  • 2021-03-20
  • 2017-06-23
  • 2018-09-13
  • 1970-01-01
相关资源
最近更新 更多