2013-10-07 4 views
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 
) 
) 
) 

Я получаю ошибку о том, что синтаксис команды неверен. Пожалуйста, помогите мне с этим.

+1

Почему вы не используете команду 'FC'? – npocmaka

+0

С помощью 'IF /?' Скобка должна быть в одной строке. 'if %% a == %% b (' – jeb

+0

@npocmaka - Команда FC не дает желаемого вывода OP, а также зависит от порядка строк, поэтому для этой проблемы совершенно неуместно. – dbenham

ответ

3

Синтаксическая ошибка вызвана неправильной помещенной открытой скобкой, но даже тогда код не работает должным образом.

Вы сравниваете каждую строку из файла1 с каждой строкой файла2, но вы производите вывод для каждого неравного сравнения, а не только если совпадение не найдено.

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 
    ) 
) 
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 ускорит его заметно.

Это может сработать, используя простой код, но в зависимости от содержимого файла1.

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

Метод FINDSTR, что foxidrive показывает, безусловно, самый быстрый способ чистого пакетного подхода к проблеме, особенно если file2 велико. Тем не менее, существует ряд сценариев, которые могут привести к его сбой: мета-характеристики regex в файле 1, кавычки и/или обратные слэши в файле 1 и т. Д. См. What are the undocumented features and limitations of the Windows FINDSTR command? для всех возможных проблем. Немного больше работы может сделать решение более надежным.

  • Поиск должен быть явно сделаны буквальным
  • Поиск должен быть точное совпадение (вся линия)
  • Любой обратный слэш в строке поиска должны быть экранированы, как \\
  • Каждый поиск должен быть сохранен в температуре файл и используемая опция \G:file

Кроме того, вы не описываете формат каждой строки. Ваши инструкции FOR/F будут читать только первое слово каждой строки из-за опции delims по умолчанию <tab> и <space>. Я подозреваю, что вы хотите установить 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 содержит \" из-за проблем эвакуации. Вы можете предварительно обработать файл2 и убрать все \, но тогда вы также можете использовать первое решение, если ограничьте себя чистым пакетным решением.

Если вы желаете использовать 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 

Обратите внимание, что это решение еще должен выполнить сравнение без учета регистра.

Смежные вопросы