使用批处理删除文件中的部分字符串

Remove part of string in file using batch

我在文本文件中有一些数据 (test.txt),阅读:

wantedunwanteddata

我想删除该字符串中的 "unwanted" 部分并输出其余部分(即 "wanteddata" 到另一个文件 (test2.txt)。我正在使用:

findstr /v "unwanted" test.txt>test2.txt

但是这会返回一个空文件。

findstr /v "unwanted" test.txt>test2.txt 不起作用的原因是 findstr 搜索符合您给它的条件的 findstr 不会 return 匹配条件的子字符串,而是满足条件的整行。在 findstr /v "unwanted" test.txt>test2.txt 中,您要求 test.txt 中没有 "unwanted" 的所有行 。这就是 test2.txt 为空的原因:没有这样的行。

在批处理中,您可以使用以下语法替换变量值中出现的所有子字符串:%var:substr=repl%。这将在 %var% 包含的字符串中用 repl 替换所有出现的 substr。由于删除子字符串类似于用空字符串替换(至少在这种情况下),您可以使用 %var:substr=% 删除所有出现的 substr.

如果你想删除文件中所有出现的子字符串,你可以在一个变量中读取该文件的每一行,for /f and print out that variable after removing the substring from it. Be aware that as we will have to create a variable inside a for /f-block and use it inside that same block, delayed expansion will be needed (this answer 解释了原因)。

@echo off
SetLocal EnableDelayedExpansion

set input=text1.txt
set output=text2.txt
set "substr=unwanted"

(
    FOR /F "usebackq delims=" %%G IN ("%input%") DO (
        set line=%%G
        echo. !line:%substr%=!
    )
) > "%output%"

EndLocal
exit /b 0

我已经在变量(分别为 inputoutput)中设置了您的输入文件 text1.txt 和输出文件 text2.txt 的(路径),没有引号(引号是使用变量时添加)。如果需要,这将使更改它们变得更容易。
for /f 周围的额外 (..) 仅用于处理到输出文件的输出重定向。
如果您不想使用延迟扩展,可以省略 SetLocal EnableDelayedExpansionEndLocal 并将 echo !line:%substr%=! 替换为 for /f 中的 call echo %%line:%substr%=%%

编辑:如果您的输入文件包含特殊字符,如<>()|&%,您必须使用延迟扩展。使用 call echo %%line:%substr%=%% 中使用的正常变量扩展,这些特殊字符将由 cmd-interpreter 以其特殊含义处理(例如 input or output redirection<>)并产生意想不到的结果。
此外,我已经包围了 substr 变量的赋值,但是如果您要替换的子字符串包含特殊字符,例如 <>()|&% ,则还必须转义每个字符,以便 %substr% 到按预期工作。您可以使用 caret-sign ^ 来转义特殊字符,除了 % 必须加倍(%% 而不是 %)。

EDIT2for /f 跳过空行,所以如果想在输出文件中保留这些空行,需要一些解决方法。纯批处理中的一个常见 hack 是使用 findstr /nfind /n 在将输入文件提供给 for /f 时在每一行(包括空行)前面加上行号。这当然需要一些额外的处理来处理 for /f 块内的行号并将它们从 for /f 的输出中删除,但这是可能的。 对类似问题提供了对这些解决方法及其缺点的极好解释。