2013-02-22 5 views
1

Мне просто нужен удобный инструмент, который проверяет наличие повторяющихся строк в текстовом файле и удаляет эти дубликаты. Так что, если файл сказал:Как проверить дубликаты в большом файле txt в пакетном режиме?

A 
B 
C 
D 
A 
E 

он превратится в:

A 
B 
C 
D 
E 

Хороший и простой. Но текстовый файл будет большим и заполнен длинными файлами, и мне нужно убедиться, что больше нет ОДНОГО из любого файла. неважно, какой из дубликатов будет удален, если останется только один. Так что я бы хорошо с чем-то вроде:

B 
C 
D 
A 
E 

Вот все, что я до сих пор:

@echo off 
SetLocal EnableDelayedExpansion 
set v=0 
FOR /F "usebackq delims=" %%a in ("SomeArray.txt") do (
set /a var+=1 
set var!v!=%%a 
) 
pause 

Я понятия не имею, где начать на делать петлю, чтобы проверить все возможные дубликаты.

+0

У меня есть код для чтения файла и установка всех строк в переменные с именем var1, var2, var3 ect. – BBMAN225

ответ

1

создать CMD файл uniqeline.cmd с этим содержимым:

@echo off 
set prev= 
for /f %%a in ('sort %1') do call :oneline %%a 
goto :eof 

:oneline 
if NOT !%1!==!%prev%! echo %1 
set prev=%1 
goto :eof 

вызова из командной строки:

uniqeline yourfilewithfilesnames.lst 
1

Ваш код для сохранения строк в "массиве" сломана. Вы должны увеличивать v вместо var.

Код для проверки дубликатов прост, но медленный. Просто пропустите существующие значения, чтобы увидеть, соответствует ли она текущей строке. Только эхо и сохранить текущую строку, если совпадение не найдено. Чем больше число уникальных линий, тем медленнее получается.

Приведенный ниже сценарий ожидает имя файла в качестве 1-го и единственного параметра

@echo off 
setlocal enableDelayedExpansion 
set n=0 
for /f "usebackq delims=" %%A in (%1) do (
    set "skip=" 
    for /l %%N in (1 1 !n!) do if "%%A"=="!var%%N!" set skip=1 
    if not defined skip (
    echo %%A 
    set /a n+=1 
    set "var!n!=%%A" 
) 
) 

выше потерпит неудачу, если строка начинается с ;, поскольку по умолчанию для опции/F EOL будет пропускать строки, начинающиеся с ;. Это может быть исправлено с некоторым неудобным синтаксисом, который устанавливает как EOL и DELIMS ни к чему: usebackq^ delims^=^ eol^=

выше будет разрушаться и если строка содержит !, потому что задержка расширения будет развратить значение линии, когда переменная FOR/F расширяется , Это можно устранить, тщательно включив и отключив отложенное расширение по мере необходимости.

@echo off 
setlocal disableDelayedExpansion 
set n=0 
for /f usebackq^ delims^=^ eol^= %%A in (%1) do (
    set "ln=%%A" 
    set "skip=" 
    setlocal enableDelayedExpansion 
    for /l %%N in (1 1 !n!) do if "!ln!"=="!var%%N!" set skip=1 
    if defined skip (endlocal) else (
    echo !ln! 
    set /a n+=1 
    for %%N in (!n!) do (
     endlocal 
     set "var%%N=%%A" 
     set "n=%%N" 
    ) 
) 
) 

Но есть гораздо более быстрые и простые решения.

Быстрое и простое возможное чистое пакетное решение состоит в том, чтобы включить содержимое строки в имя переменной. Чтобы проверить наличие дубликатов, просто проверьте, определена ли эта переменная.

@echo off 
setlocal 

:: clear existing _ variables 
for /f "eol== delims==" %%V in ('set _ 2^>nul') do set "%%V=" 

:: read and echo file, throw away duplicates (case insensitive) 
:: does not work if line contains = 
for /f usebackq^ delims^=^ eol^= %%A in (%1) do (
    if not defined _%%A (
    echo %%A 
    set "_%%A=1" 
) 
) 

Существует два основных ограничения с вышеуказанным решением.

  • Дубликат сравнения не чувствителен к регистру, поскольку имена переменных нечувствительны к регистру.

  • Решение не будет правильно обнаруживать дубликаты, содержащие =, потому что = не может быть включен в имя переменной.


Я считаю, что решение с использованием СНП Rene является лучшим обычно применяется подход, хотя код Rene имеет следующие недостатки

  • Использование ВЫЗОВ значительно снижает производительность (заметные с большими файлами)

  • Пропущенные строки ;

  • Специальные символы, такие как &|<>^ вызывают проблемы

  • Сценарий предполагает, что существует только один пробелами маркер

Недостатки легко фиксируются:

@echo off 
setlocal disableDelayedExpansion 
set "old=" 
for /f delims^=^ eol^= %%A in ('sort %1') do (
    set "new=%%A" 
    setlocal enableDelayedExpansion 
    if "!new!" equ "!old!" (endlocal) else (
    echo !new! 
    endlocal 
    set "old=%%A" 
) 
) 

Все партии решения ограничены до максимальной длины строки ~ 8191 символов.

Кроме того, все решения, указанные выше, будут пропускать пустые строки.

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