我在文本文件(test.txt)中有一些数据,读取:
wantedunwanteddata
我想删除该字符串中的“不需要的”部分并输出其余部分(即另一个文件中的“wanteddata”(test2.txt)。我正在使用:
findstr /v "unwanted" test.txt>test2.txt
然而,这将返回一个空文件。
答案 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 expansion(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
我已在变量(text1.txt
和text2.txt
)中设置(路径)输入文件input
和输出文件output
,而不包含引号(引号为在使用变量时添加)。如果需要,这将使其更容易更改
(..)
周围的额外for /f
仅用于处理输出重定向到输出文件
如果您不想使用延迟展开,则可以省略SetLocal EnableDelayedExpansion
和EndLocal
,并将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 /n
或find /n
将每行(包括空行)添加其行号,同时将输入文件提供给for /f
。这当然需要一些额外的处理来处理for /f
块内的行号并将它们从for /f
的输出中删除,但这是可能的。 This answer类似的问题为这些变通方法及其缺点提供了很好的解释。