如何使用批处理脚本从文本文件中删除重复条目。我只想在“=”符号之前删除重复项,并且每个文本文件中都存在“%%”。文本文件看起来像下面
nvarchar
我有大约30个不同的文本文件,其中包含上述类型的条目,并希望删除重复的行并希望保留第一次出现。请记住,只有在“=”符号之前才能识别重复行,并且需要删除整行。每个不同的文本文件都有“%%”符号。如果有办法通过批处理脚本或 vbscript ,请指导我?感谢
答案 0 :(得分:0)
您可以将文件读入Excel而不将其拆分为多个列。使用Excel功能消除重复并将其保存回来。你可以在VBScript中完成所有这些。
Create an Excel Object
Loop
Load text file
Remove duplicates
Save text file
Until there are no more files
Dispose of the Excel Object
单个作品的代码应该可以在网上轻松获得。请询问您可能需要的任何其他具体指示。
答案 1 :(得分:0)
这是一个简单的batch-file解决方案;让我们调用脚本rem-dups.bat
。假设输入文件为test.txt
且输出文件为result.txt
,则需要将这些文件作为命令行参数提供,因此需要通过以下方式调用它:rem-dups.bat "test.txt" "results.txt"
。这是脚本:
@echo off
setlocal EnableExtensions EnableDelayedExpansion
set "INFILE=%~1"
set "OUTFILE=%~2"
if not defined INFILE exit /B 1
if not defined OUTFILE set "OUTFILE=con"
for /F "usebackq tokens=1,* delims==" %%K in ("%INFILE%") do (
set "LEFT=%%K"
set "RIGHT=%%L"
set "LEFT=!LEFT:*%%%%=__!"
rem Remove `if` query to keep last occurrence:
if not defined !LEFT! set "!LEFT!=!RIGHT!"
)
> "%OUTFILE%" (
for /F "delims=" %%F in ('set __') do (
set "LINE=%%F"
echo(!LINE:*__=%%%%!
)
)
endlocal
exit /B
该脚本基于以下事实:不会出现重复的环境变量,具有相同的名称。
此代码仅在满足以下条件时才有效:
=
符号前面的部分字符串以%%
开头,并且至少包含一个%
以外的字符; =
之外,第一个%%
之前的部分字符串仅包含可能出现在环境变量名称中的字符; =
后的部分字符串不能为空; =
后的部分字符串不得以=
开头; !
,因为它们可能会丢失或导致其他意外结果; 以下是使用临时文件的替代方法:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "INFILE=%~1"
set "OUTFILE=%~2"
if not defined INFILE exit /B 1
if not defined OUTFILE set "OUTFILE=con"
set "TEMPFILE=%TEMP%\%~n0_%RANDOM%.tmp"
> "%TEMPFILE%" break
> "%OUTFILE%" (
for /F usebackq^ delims^=^ eol^= %%L in ("%INFILE%") do (
for /F tokens^=1^,*^ delims^=^=^ eol^= %%E in ("%%L") do (
> nul 2>&1 findstr /I /X /L /C:"%%E" "%TEMPFILE%" || (
echo(%%L
>> "%TEMPFILE%" echo(%%E
)
)
)
)
> nul 2>&1 del "%TEMPFILE%"
endlocal
exit /B
留给第一个=
符号的每个唯一(非空)令牌都写入临时文件,该文件在从输入文件中读取每一行后进行搜索。如果令牌已在临时文件中可用,则跳过该行;如果没有,则将其写入输出文件。
除非您从/I
命令中删除findstr
开关,否则将以不区分大小写的方式处理文件内容。
这里有两个经过改进的脚本,因此没有特殊字符可以使它们失败。他们不使用临时文件。两个脚本都删除具有重复关键字的行(例如,在第一个=
符号之前的部分字符串)。
如果遇到重复的关键字,此脚本会保留第一行行:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "INFILE=%~1"
set "OUTFILE=%~2"
if not defined INFILE exit /B 1
if not defined OUTFILE exit /B 1
> "%OUTFILE%" break
for /F usebackq^ delims^=^ eol^= %%L in ("%INFILE%") do (
for /F tokens^=1^ delims^=^=^ eol^= %%E in ("%%L") do (
set "LINE=%%L"
set "KEY=%%E"
setlocal EnableDelayedExpansion
if not "!LINE:~,1!"=="=" (
set "KEY=!KEY: = !"
set "KEY=!KEY:\=\\!" & set "KEY=!KEY:"=\"!"
more /T1 "%OUTFILE%" | > nul 2>&1 findstr /I /M /B /L /C:"!KEY!=" || (
>> "%OUTFILE%" echo(!LINE!
)
)
endlocal
)
)
endlocal
exit /B
如果遇到重复的关键字,此脚本会保留 last 行:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
set "INFILE=%~1"
set "OUTFILE=%~2"
if not defined INFILE exit /B 1
if not defined OUTFILE exit /B 1
> "%OUTFILE%" (
for /F delims^=^ eol^= %%L in ('findstr /N /R "^" "%INFILE%"') do (
set "LINE=%%L"
for /F "delims=:" %%N in ("%%L") do set "LNUM=%%N"
setlocal EnableDelayedExpansion
set "LINE=!LINE:*:=!"
if defined LINE if not "!LINE:~,1!"=="=" (
for /F tokens^=1^ delims^=^=^ eol^= %%E in ("!LINE!") do (
setlocal DisableDelayedExpansion
set "KEY=%%E"
setlocal EnableDelayedExpansion
set "KEY=!KEY: = !"
set "KEY=!KEY:\=\\!" & set "KEY=!KEY:"=\"!"
more /T1 +!LNUM! "%INFILE%" | > nul 2>&1 findstr /I /M /B /L /C:"!KEY!=" || (
echo(!LINE!
)
endlocal
endlocal
)
)
endlocal
)
)
endlocal
exit /B
对于这两个脚本,以下规则适用:
=
开头的行,将被忽略,因此会被删除; =
的非空行将被视为以=
结束以检查重复项,因此整行用作关键字; < / LI>
=
或 TAB 的替换不会反映在那里); /I
命令中删除findstr
开关; 以上所有脚本仅用于处理单个文件。但是,如果您需要处理多个文件,您只需编写一个包含for
循环的包装器,枚举所有输入文件,并为每个项调用上面的一个脚本(称为rem-dups.bat
) - 像这样:
@echo off
setlocal EnableExtensions DisableDelayedExpansion
rem Define constants here:
set "INPATH=D:\Data\source" & rem (location of input files)
set "OUTPATH=D:\Data\target" & rem (location of output files)
set INFILES="source.txt" "test*.txt" & rem (one or more input files)
set "OUTSUFF=_no-dups" & rem (optional suffix for output file names)
set "SUBBAT=%~dp0rem-dups.bat"
pushd "%INPATH%" || exit /B 1
for %%I in (%INFILES%) do if exist "%%~fI" (
call "%SUBBAT%" "%%~fI" "%OUTPATH%\%%~nI%OUTSUFF%%%~xI"
)
popd
endlocal
exit /B
您不能为输入和输出文件指定相同的位置。如果要覆盖原始输入文件,首先需要将修改后的输出文件写入另一个位置,然后将它们移回源位置 - 假设您已将包装器脚本中的OUTSUFF
设置为空字符串(set "OUTSUFF="
而不是set "OUTSUFF=_no-dups"
)。覆盖原始输入文件的命令行为:move /Y "D:\Data\target\*.*" "D:\Data\source"
。