Пакетная фильтрация дублирующих строк и запись в новый файл (полуфабрикат)
Я успешно создал скрипт, который отфильтровывает повторяющиеся строки в файле и сохраняет результаты в разделенную точку с запятой (своего рода "массив"). Я не мог найти действительно хорошее решение для этого.
@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 ответ
В конце вашего первого раздела, когда содержимое !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%
)