包含特殊字符的 CMD 替换短语



我需要做一件非常简单的事情:用一个frase替换另一个frase。这必须由CMD批处理文件(适用于Windows 7)完成。要替换的 frase 可以位于 txt 文件行(以及许多行)中的任何位置。

问题是要替换的 frase 包含 ":" 和 "!" 字符。我对批处理文件不是很熟练(委婉地说),尽管我花了一些时间专门了解这个特定问题。对我来说,这看起来很复杂。最后,偶然地,我忽略了这个问题,但是...我觉得我这样做是一种野蛮。

应替换的与 frase 的实线是例如:

"21:12:45 WARNING: No video signal present!"

应该替换的弗雷斯是:

"WARNING: No video signal present!"

应该用以下公式代替的 frase:

"Recognition suspended"

我找到了这段代码:https://www.computerhope.com/forum/index.php?topic=41188.0

它工作正常,除了不能与"!"一起工作,正如我所看到的,并且转义字符"^"永远不起作用。但我注意到,虽然它不能正常工作 - 它修剪了感叹号。以下是 (b) 之前和之后的实数字符串:

(b)20:42:18 WARNING: No video signal present!
(a)20:42:18 WARNING: No video signal present

所以我在代码中添加了另外 2 行,这就可以了。整个代码现在是:

@echo off
setlocal enabledelayedexpansion
set txtfile=D:wfctestlibtest.txt
set newfile=D:wfctestlibnew_test.txt
if exist "%newfile%" del /f /q "%newfile%"
for /f "tokens=*" %%a in (%txtfile%) do (
set newline=%%a
set newline=!newline:No video signal present!=!
set newline=!newline:No video signal present=!
set newline=!newline:WARNING:=Suspend recognition!
echo !newline! >> %newfile%
)

第一个关键行切"!", 第二行将"不存在视频信号"替换为任何内容(修剪它), 第三行将其余的"警告:"替换为所需的"暂停识别"。

最后我有:

(b)20:42:18 WARNING: No video signal present!
(a)20:42:18 Suspend recognition

我觉得这可以优雅地完成。此外,我不确定,我的方式是否由于某种原因(数据损坏等)不危险。请帮忙。

是的,这可以更容易完成。

首先,删除!字符的不是行set newline=!newline:No video signal present!=!,而是行set newline=%%a,因为在扩展for变量引用%%a时启用了延迟变量扩展,这发生在延迟扩展之前,因此会出现一个孤立的感叹号,只是简单地删除了。

成功的关键是在扩展%%a期间禁用延迟扩展,并在扩展后启用它。在子字符串替换语法中,:不会导致任何问题;搜索字符串中的!也没有,因为它不是第一个字符。所以下面的代码应该可以工作:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "txtfile=D:wfctestlibtest.txt"
set "newfile=D:wfctestlibnew_test.txt"
> "%newfile%" (
for /F usebackq^ delims^=^ eol^= %%a in ("%txtfile%") do (
set "newline=%%a"
setlocal EnableDelayedExpansion
echo(!newline:WARNING: No video signal present!=Recognition suspended!
endlocal
)
)
endlocal
exit /B

我还更改了以下项目:

  • 通过使用引号改进了set的语法,以避免某些特殊字符的麻烦;
  • 避免了临时变量newline,因此直接在echo行中进行字符串操作;
  • 引用文件路径/名称以避免空格问题,因此使用usebackq选项;
  • tokens=*替换为delims=选项以保留前导空格; 为了避免由于默认的eol选项而丢失以;开头的行,我使用了看起来奇怪的不带引号的选项字符串语法,因为这是没有delims并且eol同时定义的唯一方法(!)(您不能写"delims= eol="因为这会将"定义为eol字符;"eol= delims="将定义空间,并"eol=delims="d);
  • 重定向了整个for循环,因此不需要初始文件删除,并且性能要好得多,因为输出文件只需要打开和关闭一次,而不是在每次迭代中;
  • echo Text > "file.ext"返回一个尾随空格(实际上是>前面的那个); 上述项目避免了这种情况; 通常,使用反向重定向语法时可以避免这种情况> "file.ext" echo Text;
  • echo !VAR!在变量VAR为空的情况下返回ECHO is on|off.; 为了避免此输出或其他意外输出,使用了外观奇怪但安全的语法echo(!VAR!;
  • 当启用延迟扩展以避免损失!时,避免立即(%)扩展;

若要保留原始文件中显示的空行,请将代码更改为以下内容:

@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "txtfile=D:wfctestlibtest.txt"
set "newfile=D:wfctestlibnew_test.txt"
> "%newfile%" (
for /F "delims=" %%a in ('findstr /N /R "^" "%txtfile%"') do (
set "newline=%%a"
setlocal EnableDelayedExpansion
set "newline=!newline:WARNING: No video signal present!=Recognition suspended!"
echo(!newline:*:=!
endlocal
)
)
endlocal
exit /B

findstr命令用于在输入文件的每一行前面加上行号加冒号(/N选项)。然后完成子字符串替换。最后,包括第一个:的所有内容,因此行号前缀被删除。

在.bat文件脚本中替换短语非常容易。

powershell -NoLogo -NoProfile -Command ^
"Get-Content -Path '.subfrase-in.txt' |" ^
"ForEach-Object { $_ -replace 'WARNING: No video signal present!', 'Recognition suspended' }"

最新更新