【问题标题】:Comparing two files in batch script比较批处理脚本中的两个文件
【发布时间】:2013-10-07 11:12:46
【问题描述】:

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

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

【问题讨论】:

  • 为什么不用FC 命令?
  • 来自帮助IF /? 括号必须在同一行。 if %%a==%%b (
  • @npocmaka - FC 命令没有给出 OP 所需的输出。它也依赖于线序,因此完全不适合这个问题。

标签: batch-file file-comparison


【解决方案1】:

foxidrive 展示的 FINDSTR 方法绝对是解决问题的最快的纯批处理方法,尤其是在 file2 很大的情况下。但是,有许多情况可能导致它失败:文件 1 中的正则表达式元字符、文件 1 中的引号和/或反斜杠等。请参阅What are the undocumented features and limitations of the Windows FINDSTR command? 了解所有潜在问题。多做一点工作可以使解决方案更可靠。

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

另外,你没有描述每一行的格式。由于<tab><space> 的默认delims 选项,您的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

如果您的 file2 不包含 \" 并且您可以进行不区分大小写的搜索,则有一个非常快速的单行解决方案:只需反转 FINDSTR 搜索以查找 file1 中不存在于文件中的任何行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 对标准输入的每一行执行正则表达式搜索和替换操作,并将结果写入标准输出。

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

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

【讨论】:

    【解决方案2】:

    语法错误是由错误放置的左括号引起的,但即使这样,代码也不能按预期工作。

    您将 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
        )
    )
    

    【讨论】:

      【解决方案3】:

      试一试:

      @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
      )
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-08-19
        • 2022-12-14
        • 1970-01-01
        • 1970-01-01
        • 2013-11-04
        • 1970-01-01
        • 1970-01-01
        • 2022-10-18
        相关资源
        最近更新 更多