Пакетная фильтрация дублирующих строк и запись в новый файл (полуфабрикат) - PullRequest
0 голосов
/ 15 ноября 2011

Я успешно создал скрипт, который отфильтровывает повторяющиеся строки в файле и сохраняет результаты в разделенную точку с запятой (своего рода «массив»).Я не смог найти действительно хорошего решения.

@echo off
setlocal enabledelayedexpansion

rem test.txt contains:
rem 2007-01-01
rem 2007-01-01
rem 2007-01-01
rem 2008-12-12
rem 2007-01-01
rem 2009-06-06
rem ... and so on

set file=test.txt

for /f "Tokens=* Delims=" %%i in ('type %file%') do (
    set read=%%i
    set read-array=!read-array!;!read!
)

rem removes first trailing ";"
set read-array=!read-array:*;=!
echo !read-array!

for /f "Tokens=* Delims=" %%i in ('type %file%') do (
    set dupe=0
    rem searches array for the current read line (%%i) and if it does exist, it deletes ALL occurences of it
    echo !read-array! | find /i "%%i" >nul && set dupe=1
    if ["!dupe!"] EQU ["1"] (
        set read-array=!read-array:%%i;=!
        set read-array=!read-array:;%%i=!
    )
    rem searches array for the current read line (%%i) and if it does not exist, it adds it once
    echo !read-array! | find /i "%%i" >nul || set read-array=!read-array!;%%i
)

rem results: no duplicates
echo !read-array!

Содержимое !read-array! равно 2008-12-12;2007-01-01;2009-06-06

Теперь я хочу вынуть каждый элемент в массиве и записать их вновый файл с разрывами строк после каждого элемента.Пример:

2008-12-12
2007-01-01
2009-06-06

Так вот, что я до сих пор придумал.

Проблема, с которой я столкнулся , заключается в том, что второй forЦикл не принимает переменную !loop! в качестве определения токена при вложении.Однако он принимает %loop%, если он не вложенный.Причина, по которой я делаю это таким образом, заключается в том, что !read-array! может иметь неизвестное количество предметов, поэтому я также считаю их.Есть идеи?

rem count items in array
set c=0
for %%i in (!read-array!) do set /a c+=1

echo %c% items in array
for /l %%j in (1,1,%c%) do (
    set loop=%%j
    for /f "Tokens=!loop! Delims=;" %%i in ("!read-array!") do (
        echo %%i
        rem echo %%i>>%file%
    )
)
exit /b

1 Ответ

2 голосов
/ 16 ноября 2011

В конце вашего первого раздела, когда содержимое !read-array! равно 2008-12-12;2007-01-01;2009-06-06, вы можете напрямую отделить элементы вашего «списка» простым for, потому что стандартные разделители в пакетных файлах могут быть, кроме пробелов, запятая, точка с запятой или знак равенства:

for %%i in (%read-array%) do echo %%i

Тем не менее, могу ли я предложить вам более простой метод?

Почему бы не определить «реальный» массив с нижним значением строк?Таким образом, несколько повторяющихся строк сохранят свое значение в одном элементе массива.В конце просто отобразите значения результирующих элементов:

@echo off
set file=test.txt
for /F "Delims=" %%i in (%file%) do (
    set read-array[%%i]=%%i
)
rem del %file%
for /F "Tokens=2 Delims==" %%i in ('set read-array[') do (
    echo %%i
    rem echo %%i>>%file%
)

РЕДАКТИРОВАТЬ Альтернативное решение

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

@echo off
setlocal EnableDelayedExpansion
set file=test.txt
for /F "Delims=" %%i in (%file%) do (
    set read-array=!read-array:;%%i=!;%%i
)
rem del %file%
for %%i in (%read-array%) do (
    echo %%i
    rem echo %%i>> %file%
)
...