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

时间:2017-02-14 10:49:19

标签: batch-file findstr

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

wantedunwanteddata

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

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

然而,这将返回一个空文件。

1 个答案:

答案 0 :(得分:4)

findstr /v "unwanted" test.txt>test2.txt无法发挥作用的原因是因为findstr搜索与您提供的条件匹配的findstr不会返回与条件匹配的子字符串,而是返回满足条件的整行。在findstr /v "unwanted" test.txt>test2.txt中,您要求 test.txt中的所有行没有"不需要的"在它。这就是test2.txt为空的原因:没有这样的行。

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

如果要删除文件中子字符串的所有出现,可以使用for /f读取变量中该文件的每一行,并在从中删除子字符串后打印出该变量。请注意,由于我们必须在for /f - 块中创建变量并在同一个块中使用它,因此需要delayed expansionthis 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

我已在变量(text1.txttext2.txt)中设置(路径)输入文件input和输出文件output,而不包含引号(引号为在使用变量时添加)。如果需要,这将使其更容易更改 (..)周围的额外for /f仅用于处理输出重定向到输出文件 如果您不想使用延迟展开,则可以省略SetLocal EnableDelayedExpansionEndLocal,并将echo !line:%substr%=!替换为call echo %%line:%substr%=%% for /f

编辑:如果您的输入文件包含<>()|&%等特殊字符,则必须使用延迟扩展。使用call echo %%line:%substr%=%%中使用的常规变量扩展,这些特殊字符将由cmd-interpreter(例如< >input or output redirection的特殊含义处理)并生成意想不到的结果 此外,我已经包含了substr变量的分配,但如果您尝试替换的子字符串包含<>()|&%之类的特殊字符,则每个字符也必须进行转义,以便%substr% 1}}按预期工作。您可以使用插入符号^来转义特殊字符,但必须加倍的%除外(%%而不是%)。

EDIT2 for /f跳过空白行,因此如果想要在输出文件中保留这些空行,则需要一些解决方法。纯批处理中常见的黑客攻击方法是使用findstr /nfind /n将每行(包括空行)添加其行号,同时将输入文件提供给for /f。这当然需要一些额外的处理来处理for /f块内的行号并将它们从for /f的输出中删除,但这是可能的。 This answer类似的问题为这些变通方法及其缺点提供了很好的解释。