0

我正在尝试以这种方式比较两个文件,文件 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
)
)
)

我收到一条错误消息,该命令的语法不正确。请帮我解决一下这个。

4

3 回答 3

5

foxidrive 显示的 FINDSTR 方法绝对是解决问题的最快的纯批处理方法,尤其是在 file2 很大的情况下。但是,有许多情况可能导致它失败:文件 1 中的正则表达式元字符、文件 1 中的引号和/或反斜杠等。请参阅Windows FINDSTR 命令的未记录功能和限制是什么?对于所有潜在的问题。更多的工作可以使解决方案更可靠。

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

另外,您没有描述每一行的格式。由于and的默认delims选项,您的 FOR /F 语句将只读取每行的第一个单词。我怀疑你想设置为空。您还希望禁用该选项,以便不跳过以开头的行。这需要一些看起来很奇怪的语法。我添加了该选项,以防您处理必须引用的文件名。<tab><space>delimseol;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

如果您的 file2 不包含\"并且您可以进行不区分大小写的搜索,则有一个非常快速的单行解决方案:只需反转 FINDSTR 搜索以查找 file1 中不存在于文件 2 中的任何行。搜索必须是不区分大小写,因为为什么这个具有多个文字搜索字符串的 FINDSTR 示例找不到匹配项?.

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

\"如果 file2 包含由于转义问题,这将不起作用。您可以预处理 file2 并转义 all \,但是如果您将自己限制为纯批处理解决方案,那么您不妨使用第一个解决方案。

如果您愿意使用名为 REPL.BAT 的混合 JScript/批处理实用程序,那么我有一个非常简单和有效的解决方案。REPL.BAT 对标准输入的每一行执行正则表达式搜索和替换操作,并将结果写入标准输出。

假设 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

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

于 2013-10-07T13:23:38.730 回答
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
    )
)
于 2013-10-07T11:26:00.433 回答
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
)
于 2013-10-07T11:54:33.413 回答