是否可以从文本文件中删除重复的行?如果有,怎么样?
答案 0 :(得分:13)
当然可以,但像批量处理的大多数文本文件一样,它并不漂亮,而且速度也不是很快。
此解决方案在查找重复项时忽略大小写,并对行进行排序。该文件的名称作为批处理脚本的第一个也是唯一的参数传入。
@echo off
setlocal disableDelayedExpansion
set "file=%~1"
set "sorted=%file%.sorted"
set "deduped=%file%.deduped"
::Define a variable containing a linefeed character
set LF=^
::The 2 blank lines above are critical, do not remove
sort "%file%" >"%sorted%"
>"%deduped%" (
set "prev="
for /f usebackq^ eol^=^%LF%%LF%^ delims^= %%A in ("%sorted%") do (
set "ln=%%A"
setlocal enableDelayedExpansion
if /i "!ln!" neq "!prev!" (
endlocal
(echo %%A)
set "prev=%%A"
) else endlocal
)
)
>nul move /y "%deduped%" "%file%"
del "%sorted%"
此解决方案区分大小写,它以原始顺序保留行(当然,重复除外)。同样,文件的名称作为第一个和唯一的参数传入。
@echo off
setlocal disableDelayedExpansion
set "file=%~1"
set "line=%file%.line"
set "deduped=%file%.deduped"
::Define a variable containing a linefeed character
set LF=^
::The 2 blank lines above are critical, do not remove
>"%deduped%" (
for /f usebackq^ eol^=^%LF%%LF%^ delims^= %%A in ("%file%") do (
set "ln=%%A"
setlocal enableDelayedExpansion
>"%line%" (echo !ln:\=\\!)
>nul findstr /xlg:"%line%" "%deduped%" || (echo !ln!)
endlocal
)
)
>nul move /y "%deduped%" "%file%"
2>nul del "%line%"
的 修改 强>
上述两种解决方案均剥离空行。在谈论不同的价值观时,我不认为空白行是值得保留的。
我修改了两个解决方案以禁用FOR / F“EOL”选项,以便保留所有非空行,无论第一个字符是什么。修改后的代码将EOL选项设置为换行符。
新解决方案2016-04-13:JSORT.BAT
您可以使用我的JSORT.BAT hybrid JScript/batch utility使用简单的一行(有一个MOVE来覆盖原始文件和最终结果)来有效地排序和删除重复的行。 JSORT是纯脚本,可以在XP以后的任何Windows机器上本机运行。
@jsort file.txt /u >file.txt.new
@move /y file.txt.new file.txt >nul
答案 1 :(得分:9)
答案 2 :(得分:3)
set "file=%CD%\%1"
sort "%file%">"%file%.sorted"
del /q "%file%"
FOR /F "tokens=*" %%A IN (%file%.sorted) DO (
SETLOCAL EnableDelayedExpansion
if not [%%A]==[!LN!] (
set "ln=%%A"
echo %%A>>"%file%"
)
)
ENDLOCAL
del /q "%file%.sorted"
这应该完全相同。那个dbenham的例子对我来说似乎太硬了,所以,测试了我自己的解决方案。用法例如:filedup.cmd filename.ext
答案 3 :(得分:3)
下面的批处理文件可以执行您想要的操作:
@echo off
setlocal EnableDelayedExpansion
set "prevLine="
for /F "delims=" %%a in (theFile.txt) do (
if "%%a" neq "!prevLine!" (
echo %%a
set "prevLine=%%a"
)
)
如果您需要更高效的方法,请尝试使用此开发为过滤器的Batch-JScript混合脚本,即类似于Unix uniq
程序。使用.bat扩展名保存,例如uniq.bat
:
@if (@CodeSection == @Batch) @then
@CScript //nologo //E:JScript "%~F0" & goto :EOF
@end
var line, prevLine = "";
while ( ! WScript.Stdin.AtEndOfStream ) {
line = WScript.Stdin.ReadLine();
if ( line != prevLine ) {
WScript.Stdout.WriteLine(line);
prevLine = line;
}
}
这两个程序都是从this post复制的。
答案 4 :(得分:2)
纯批次 - 3个有效行。
@ECHO OFF
SETLOCAL
:: remove variables starting $
FOR /F "delims==" %%a In ('set $ 2^>Nul') DO SET "%%a="
FOR /f "delims=" %%a IN (q34223624.txt) DO SET $%%a=Y
(FOR /F "delims=$=" %%a In ('set $ 2^>Nul') DO ECHO %%a)>u:\resultfile.txt
GOTO :EOF
如果数据不包含批次具有敏感性的字符,请立即使用。
" q34223624.txt"因为问题34223624包含这个数据
1.1.1.1
1.1.1.1
1.1.1.1
1.2.1.2
1.2.1.2
1.2.1.2
1.3.1.3
1.3.1.3
1.3.1.3
它完美地运作。
答案 5 :(得分:1)
遇到过这个问题并且必须自己解决,因为使用对我来说是微不足道的。 我需要找到重复的URL并且行的顺序是相关的,因此需要保留它。文本行不应包含任何双引号,不应该很长,并且不能使用排序。
因此我这样做了:
setlocal enabledelayedexpansion
type nul>unique.txt
for /F "tokens=*" %%i in (list.txt) do (
find "%%i" unique.txt 1>nul
if !errorlevel! NEQ 0 (
echo %%i>>unique.txt
)
)
辅助:如果文本确实包含双引号,那么FIND需要使用过滤后的set变量,如本文所述:Escape double quotes in parameter
所以而不是:
find "%%i" unique.txt 1>nul
更像是:
set test=%%i
set test=!test:"=""!
find "!test!" unique.txt 1>nul
因此,find会像find""""""文件和%%我将保持不变。
答案 6 :(得分:1)
我使用了假#34阵列"完成这个
@echo off
:: filter out all duplicate ip addresses
REM you file would take place of %1
set file=%1%
if [%1]==[] goto :EOF
setlocal EnableDelayedExpansion
set size=0
set cond=false
set max=0
for /F %%a IN ('type %file%') do (
if [!size!]==[0] (
set cond=true
set /a size="size+1"
set arr[!size!]=%%a
) ELSE (
call :inner
if [!cond!]==[true] (
set /a size="size+1"
set arr[!size!]=%%a&& ECHO > NUL
)
)
)
break> %file%
:: destroys old output
for /L %%b in (1,1,!size!) do echo !arr[%%b]!>> %file%
endlocal
goto :eof
:inner
for /L %%b in (1,1,!size!) do (
if "%%a" neq "!arr[%%b]!" (set cond=true) ELSE (set cond=false&&goto :break)
)
:break
使用内部循环的标签是cmd.exe特有的,是我成功嵌套彼此循环的唯一方法。基本上,这将比较作为分隔符传递的每个新值,如果没有匹配,则程序将该值添加到内存中。完成后,它将销毁目标文件内容并用唯一字符串
替换它们答案 7 :(得分:0)
前段时间,我找到了一个出乎意料的简单解决方案,但是不幸的是,该解决方案仅在Windows 10上有效:sort
command具有一些可以采用的未记录选项:
/UNIQ[UE]
仅输出唯一的行; /C[ASE_SENSITIVE]
区分大小写; 因此,使用以下代码行删除重复的行(删除/C
以不区分大小写的方式进行操作):
sort /C /UNIQUE "incoming.txt" /O "outgoing.txt"
这将从incoming.txt
中的文本中删除重复的行,并在outgoing.txt
中提供结果。关于原始顺序当然不会被保留(因为这是sort
的主要目的)。
但是,您应该谨慎使用这些选项,因为它们可能存在一些(未知)问题,因为(到目前为止)可能有充分的理由不对它们进行记录。