批处理:&符号导致 findstr 出现问题

batch: ampersand causing issues with findstr

这部分工作正常,直到文件名中有一个符号,在这种情况下,它会完全崩溃我的脚本。

echo %filename% | findstr /i /b /c:"%name% (%year%)"

我不能只把文件名放在引号里,因为我需要找到开头的字符串。那么我怎样才能做到这两点呢?

命令行使用:

echo %file^name:^&=^^^&% | ...

在批处理文件中

echo %%filename:^&=^^^&%% | ...

如何运作?
当管道创建两个新的 cmd.exe 实例时,echo ... 将被解析两次。
诀窍是只在第二次扩展时扩展文件名。
然后扩展 & 并将其替换为 ^& 以避免 &.
出现问题 插入符号将用于转义 & 符号,它本身将被删除。
在第二次扩展中,解析器只看到 echo %filename:&=^&%

要强制扩展到第二个解析步骤,批处理文件的百分号必须加倍。
在命令行中,这不起作用,但变量名中任意位置的简单插入符号都有效。

备选方案:

echo "%filename%" | findstr /i /b /c:^"\"%filename% (%year%)\""

这仅添加引号并在搜索表达式中也使用引号

另一种选择是使用延迟扩展,这需要使用 /v:on 选项的显式 cmd

cmd /v:on /c "(echo !filename!)" | findstr /i /b /c:"%name% (%year%)"

如果您的批处理脚本已经启用了延迟扩展,则需要在左侧加上括号以防止在父脚本中发生延迟扩展(参见Why does delayed expansion fail when inside a piped block of code?.子进程仍将默认禁用延迟扩展,因此仍然需要 cmd /v:on /c ...

@echo off
setlocal enableDelayedExpansion
...
(cmd /v:on /c "(echo !filename!)") | findstr /i /b /c:"%name% (%year%)"

另一种延迟扩展直到子进程的方法是逃逸扩展

@echo off
setlocal enableDelayedExpansion
...
cmd /v:on /c "(echo ^!filename^!)" | findstr /i /b /c:"%name% (%year%)"