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

时间:2018-04-02 15:31:48

标签: batch-file cmd windows-7

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

问题是要替换的frase包含“:”和“!”字符。我对批处理文件不是很熟练(说得温和一点),虽然我花了几个小时来特别了解这个具体问题。对我来说这看起来很复杂。最后,偶然的,我覆盖了这个问题,但是......我觉得我做的很野蛮。

应该替换的frase的实际行是例如:

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

应该替换的frase是:

"WARNING: No video signal present!"

应该替换的frase是:

"Recognition suspended"

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

它工作正常,但不能用“!”正如我所见,逃避char“^”永远不会奏效。但我注意到虽然它不能正常工作 - 它会修剪感叹号。以下是(b)之前和(a)之后的真实字符串:

(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:\wfc\testlib\test.txt
set newfile=D:\wfc\testlib\new_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

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

2 个答案:

答案 0 :(得分:1)

是的,这可以更轻松。

首先,删除set newline=!newline:No video signal present!=!字符的行!不是行set newline=%%a,而是%%a行,因为在{%%a时启用了delayed variable expansion {3}}变量引用:已展开,在延迟扩展之前发生,因此会出现一个孤立的感叹号,只是被移除。

成功的关键是在!扩展期间禁用延迟扩展并在之后启用它。在for中,@echo off setlocal EnableExtensions DisableDelayedExpansion set "txtfile=D:\wfc\testlib\test.txt" set "newfile=D:\wfc\testlib\new_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 不会导致任何问题;搜索字符串中的newline也不是,因为它不是第一个字符。所以下面的代码应该可以工作:

echo

我还更改了以下项目:

  • 使用引号改进了sub-string replacement syntax的语法,以避免出现某些特殊字符的问题;
  • 避免使用临时变量tokens=*,直接在;行中进行字符串操作;
  • 引用文件路径/名称以避免出现空格问题,因此使用set选项;
  • delims替换为usebackq选项,以保持领先的空格;为了避免由于默认delims=选项而丢失以eol开头的行,我使用了奇怪的不带引号的选项字符串语法,因为这是唯一的方式(!)没有{{1}和"delims= eol="同时定义(你不能写"因为这会将eol定义为"eol= delims="字符; "eol=delims="会定义 SPACE d for);
  • eol整个echo Text > "file.ext"循环,因此不需要删除初始文件,性能要好得多,因为输出文件必须只打开和关闭一次,而不是每次迭代; < / LI>
  • >返回一个尾随的空格(实际上是> "file.ext" echo Text前面的那个);上述项目可以避免这种情况;通常,使用反向重定向语法echo !VAR!;
  • 时可以避免这种情况 如果变量ECHO is on|off.为空,则
  • VAR会返回echo(!VAR!;为了避免这种或其他意外的输出,使用奇怪但安全的语法%;
  • 在启用延迟展开时避免立即(!)扩展,以避免丢失@echo off setlocal EnableExtensions DisableDelayedExpansion set "txtfile=D:\wfc\testlib\test.txt" set "newfile=D:\wfc\testlib\new_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 ;

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

/N

redirected用于为输入文件的每一行添加一个行号加冒号(:选项)。然后完成子串替换。最后,所有内容都包括第一个{{1}},因此行号前缀将被删除。

答案 1 :(得分:0)

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

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