您将行存储在“数组”中的代码已损坏。您应该递增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"
)
)
上述解决方案有两个主要限制。
我相信 rene 使用 SORT 的解决方案是最好的普遍适用的方法,虽然 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 个字符。
此外,上述所有解决方案都会去除空行。