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

Posted

技术标签:

【中文标题】包含特殊字符的 CMD 替换短语【英文标题】:CMD substitute phrase containing special characters 【发布时间】:2018-09-11 20:03:36 【问题描述】:

我需要做一件非常简单的事情:用一个框架替换另一个框架。这必须通过 CMD 批处理文件完成(对于 Windows 7)。被替换的帧可以在txt文件行中的任意位置(也可以在多行中)。

问题是要替换的框架包含“:”和“!”人物。我对批处理文件不是很熟练(委婉地说),尽管我花了几个小时专门来了解这个特定问题。对我来说看起来很复杂。最后,一次偶然的机会,我忽略了这个问题,但是......我觉得我这样做是野蛮的。

应该替换的带有框架的实际行是例如:

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

应该替换的框架是:

"WARNING: No video signal present!"

它应该被替换的框架是:

"Recognition suspended"

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

它工作正常,除了不能使用“!”如我所见,转义字符“^”永远不会起作用。但我注意到虽然它不能正常工作 - 它修剪了感叹号。以下是 (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

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

【问题讨论】:

【参考方案1】:

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

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

成功的关键是在%%a的扩展过程中禁用延迟扩展,然后再启用它。在sub-string replacement syntax: 不会造成任何问题;搜索字符串中的! 也不是,因为它不是第一个字符。所以下面的代码应该可以工作:

@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

我还更改了以下项目:

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

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

【讨论】:

"usebackq tokens=* 是一个糟糕的选择,因为它会去除前导空格和制表符。最好使用"usebackq delims="。但是由于默认 EOL,: 仍然存在问题。最好的选择是看起来很糟糕的usebackq^ delims^=^ eol^=,没有任何引号,因为它禁用了 DELIMS 和 EOL。 非常感谢 aschipfl。这行得通。虽然我昨天来了另一个问题 - 真实文件中有一些空行 对不起,我偶然按了 Enter - 完整的评论是:非常感谢 aschipfl。这行得通。虽然我昨天来了另一个问题 - 真实文件中有一些空行。看起来必须保留这些空行,否则文件将无用...也感谢 dbenham - 它也可以正常工作,即使以我的虫眼观点,我也无法理解那里的曲折。最好的,麦克。 要保持空行,看看this post... 非常感谢。但是有一个问题 - 空行充满了ECHO jest wyĄczone,这意味着波兰语中的"ECHO is off"【参考方案2】:

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

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

【讨论】:

怀疑 OP 被否决。也许您说的是批处理文件但随后使用了 poweshell 的事实?是的,您可以批量包装 powershell,但为什么不单独使用 powershell? 我同意仅使用 PowerShell,但 OP 指定它必须“通过 CMD 批处理”完成。有些人不介意使用find.exetaskkill.exenet.exe,但不愿使用powershell.exe。这只是机器上的另一个命令。为什么不应该使用它? 我只是在考虑投反对票的原因。也许只是指定批量包装powershell命令。

以上是关于包含特殊字符的 CMD 替换短语的主要内容,如果未能解决你的问题,请参考以下文章

linux 特殊符号怎样用sed替换

替换包含特殊字符的文本中的行(数学方程)linux文本

sed 用特殊字符替换字符串

js 如何判断输入的字符串中含有特殊字符。最好有例子啊

java用正则表达式判定特殊字符是不是,存在就替换的问题?

正则表达式替换特殊符号(高分)