在批处理脚本中比较两个文件

时间:2013-10-07 11:12:47

标签: batch-file file-comparison

我试图以这种方式比较两个文件,文件1的每一行将与文件2的每一行进行比较,如果没有找到匹配,则将该行写入单独的文件。

下面是我编写的代码,但它没有按预期工作,

@echo on
cd path
for /f %%a in (file1.txt) do (
for /f %%b in (file2.txt) do (
if %%a==%%b
(
echo lines are same
) else (
echo %%a >> file3.txt
)
)
)

我收到错误消息,该命令的语法不正确。 请帮帮我。

3 个答案:

答案 0 :(得分:5)

foxidrive显示的FINDSTR方法肯定是解决问题的最快的纯批处理方式,特别是如果file2很大。但是,有许多方案可能导致其失败:文件1中的正则表达式元字符,文件1中的引号和/或反斜杠等。有关所有潜在问题,请参阅What are the undocumented features and limitations of the Windows FINDSTR command?。更多的工作可以使解决方案更可靠。

  • 搜索应明确地为文字
  • 搜索应该完全匹配(整行)
  • 搜索行中的任何反斜杠都应转义为\\
  • 每次搜索都应存储在临时文件中,并使用\G:file选项

另外,您没有描述每一行的格式。由于delims<tab>的默认<space>选项,您的FOR / F语句只会读取每行的第一个单词。我怀疑你想把delims设置为空。您还要禁用eol选项,以便不跳过以;开头的行。这需要一些奇怪的语法。我添加了usebackq选项,以防您处理必须引用的文件名。

@echo off
setlocal disableDelayedExpansion
set "file1=file1.txt"
set "file2=file2.txt"
set "file3=file3.txt"
set "search=%temp%\search.txt"

>"%file3%" (
  for /f usebackq^ delims^=^ eol^= %%A in ("%file1%") do if "%%A" neq "" (
    set "ln=%%A"
    setlocal enableDelayedExpansion
    (echo(!ln:\=\\!) >"%search%"
    findstr /lxg:"%search%" "%file2%" >nul || (echo(!ln!)
    endlocal
  )
)
del "%search%" 2>nul

如果你的文件2不包含\"并且你可以负担不区分大小写的搜索,那么有一个非常快的单行解决方案:只需反转FINDSTR搜索以查找file1中不包含的任何行。 t存在于文件2中。由于Why doesn't this FINDSTR example with multiple literal search strings find a match?,搜索必须不区分大小写。

findstr /livxg:"file2.txt" "file1.txt" >"file3.txt"

如果由于转义问题而导致file2包含\",则无效。您可以预处理file2并转义所有\,但如果您将自己限制为纯批处理解决方案,那么您也可以使用第一个解决方案。

如果您愿意使用hybrid JScript/batch utility called REPL.BAT,那么我有一个非常简单有效的解决方案。 REPL.BAT对stdin的每一行执行正则表达式搜索和替换操作,并将结果写入stdout。

假设REPL.BAT位于您当前的目录中,或者更好,位于您的路径中的某个位置:

@echo off
setlocal
set "file1=file1.txt"
set "file2=file2.txt"
set "file3=file3.txt"
set "search=%temp%\search.txt"

type "%file2%"|repl \\ \\ >"%search%"
findstr /livxg:"%search%" "%file1%" >"%file3%"
del "%search%" 2>nul

请注意,此解决方案仍必须执行不区分大小写的比较。

答案 1 :(得分:3)

语法错误是由错误的左括号引起的,但即使这样代码也无法正常工作。

你将file1中的每一行与file2的每一行进行比较,但是你输出的是每次不等的比较,而不仅仅是找不到匹配。

for /f %%a in (file1.txt) do (
    set "matchFound="
    for /f %%b in (file2.txt) do (
        if %%a==%%b (
            echo lines are same
            set matchFound=1
        )
    )

    if not defined matchFound (
        echo %%a is not found in file2
    )
)

答案 2 :(得分:1)

放手一搏:

@echo on
cd /d "c:\path"
del file3.txt 2>nul
for /f "delims=" %%a in (file1.txt) do (
   set "flag="
     for /f "delims=" %%b in (file2.txt) do (
       if "%%a"=="%%b" set flag=1
     )
   if not defined flag >>file3.txt echo %%a
)

如果您的文件很大并且需要速度,那么将数组设置为file2的内容会显着加快速度。

这也可以使用更简单的代码,但取决于file1的内容。

@echo on
cd /d "c:\path"
del file3.txt 2>nul
for /f "delims=" %%a in (file1.txt) do (
     findstr "^%%a$" file2.txt >nul || >>file3.txt echo %%a
)