Windows 批处理:根据(fileA.txt减去fileB.txt)的结果创建fileC.txt
我正在尝试创建一个批处理,该批处理创建一个fileC.txt,其中包含fileA.txt中的所有行,但不包括fileB.txt中包含字符串的行: 伪:Windows 批处理:根据(fileA.txt减去fileB.txt)的结果创建fileC.txt,windows,batch-file,foreach,Windows,Batch File,Foreach,我正在尝试创建一个批处理,该批处理创建一个fileC.txt,其中包含fileA.txt中的所有行,但不包括fileB.txt中包含字符串的行: 伪: foreach(line L in fileA.txt) excluded = false foreach(string str in fileB.txt) if L contains str exclude = true if !excluded
foreach(line L in fileA.txt)
excluded = false
foreach(string str in fileB.txt)
if L contains str
exclude = true
if !excluded
add L to fileC.txt
如果我!包含
比如说
fileA.txt:(全部)
fileB.txt:(那些被排除在外)
fileC.txt:(想要的结果)
我一直在摆弄FINDSTR,但我似乎无法把它拼在一起。。非常感谢任何帮助或指点
干杯!
/Fredde答案应该很简单:
findstr /lvg:"fileB.txt" "fileA.txt" >fileC.txt
就你的例子来说,上面给出了正确的结果
但在使用多个区分大小写的文本搜索字符串时,有一个令人讨厌的FINDSTR bug使得它不可靠。看,以及随之而来的答案。有关未记录的FINDSTR功能和bug的“完整”列表,请参阅
因此,根据文件的内容,上面的简单代码可能会失败。如果可以使用不区分大小写的搜索,那么解决方案很简单
findstr /livg:"fileB.txt" "fileA.txt" >fileC.txt
编辑:如果fileB.txt包含\\
或\“
,上述两个版本都将失败。为了正常工作,必须将这些字符串转义为\\\\
和\”
但如果必须使用区分大小写的搜索,那么就没有简单的解决方案。纯批处理解决方案的最佳选择可能是使用/R正则表达式选项。但是,您必须创建一个fileB.txt的修改版本,其中所有regex元字符都将转义,以便字符串提供正确的文本搜索。这本身就是一个小型项目
对于区分大小写的解决方案,您最好的选择可能是使用第三方工具,如grep或sed for Windows
编辑:这是一个性能合理的纯批量解决方案,几乎是防弹的
我考虑过做一些类似于你问题中提出的逻辑的事情。但使用批处理读取文件中的所有行相对较慢。此解决方案仅逐行读取排除文件。它使用FINDSTR重复读取“fileA.txt”中的行,每个搜索字符串读取一次。对于批处理文件,这是一种更快的算法
读取文件的传统方法是使用FOR/F循环,但还有另一种使用SET/p的技术速度更快,并且可以安全地使用延迟扩展。此方法的唯一限制是:
- 它将从行中删除尾随的控制字符
- 它限制为每行1021字节
- 按照Windows标准,每行必须以
结尾。它不适用于以
\
和“
转义为\
和\”
@echo off
setlocal enableDelayedExpansion
copy fileA.txt fileC.txt >nul
for /f %%N in ('find /c /v "" ^<fileB.txt') do set len=%%N
<fileB.txt (
for /l %%N in (1 1 !len!) do (
set "ln="
set /p "ln="
if defined ln (
set "ln=!ln:\=\\!"
set ln=!ln:"=\"!
move /y fileC.txt temp.txt >nul
findstr /lv /c:"!ln!" temp.txt >fileC.txt
)
)
)
del temp.txt
type fileC.txt
@echo关闭
setlocal enableDelayedExpansion
复制fileA.txt fileC.txt>nul
对于('find/c/v“^中的/f%%N('find/c/v“^非常详细和令人满意的答案!即使你的第一个解决方案对我来说已经足够了*我非常喜欢阅读你的整个帖子!如果我可以,我会投票给它!我向你鞠躬,哦,明智的德本汉姆!谢谢:)*双关语
findstr /lvg:"fileB.txt" "fileA.txt" >fileC.txt
findstr /livg:"fileB.txt" "fileA.txt" >fileC.txt
@echo off
setlocal enableDelayedExpansion
copy fileA.txt fileC.txt >nul
for /f %%N in ('find /c /v "" ^<fileB.txt') do set len=%%N
<fileB.txt (
for /l %%N in (1 1 !len!) do (
set "ln="
set /p "ln="
if defined ln (
set "ln=!ln:\=\\!"
set ln=!ln:"=\"!
move /y fileC.txt temp.txt >nul
findstr /lv /c:"!ln!" temp.txt >fileC.txt
)
)
)
del temp.txt
type fileC.txt