我只需要一个方便的小工具来检查文本文件中的重复行,它将删除那些重复的行。所以如果文件说:
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 :(得分: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 :(得分:1)
将行存储在“数组”中的代码已损坏。您应该递增v
而不是var
。
检查重复项的代码很简单,但速度很慢。只需遍历现有值即可查看它是否与当前行匹配。如果未找到匹配项,则仅回显并存储当前行。唯一线的数量越多,它就越慢。
下面的脚本要求将文件名作为第一个且唯一的参数
@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"
)
)
如果一行以;
开头,则上述操作将失败,因为默认的FOR / 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"
)
)
上述解决方案有两个主要限制。
重复比较不区分大小写,因为变量名称不区分大小写。
该解决方案无法正确检测包含=
的重复项,因为=
无法包含在变量名称中。
我认为使用SORT的rene解决方案是最常用的方法,尽管rene的代码有以下缺点
使用CALL会显着降低性能(大文件会引人注意)
跳过以;
开头的行
&
|
<
>
^
等特殊字符会导致问题
该脚本假定只有一个以空格分隔的标记
缺点很容易解决:
@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个字符。
此外,上述所有解决方案都会删除空行。