Batch file 如何使用批处理脚本或vb脚本从文本文件中删除重复条目?
如何使用批处理脚本从文本文件中删除重复条目。我想要删除“=”符号和“%%”之前的重复项的所有内容都存在于每个文本文件中。文本文件如下所示Batch file 如何使用批处理脚本或vb脚本从文本文件中删除重复条目?,batch-file,vbscript,Batch File,Vbscript,如何使用批处理脚本从文本文件中删除重复条目。我想要删除“=”符号和“%%”之前的重复项的所有内容都存在于每个文本文件中。文本文件如下所示 %%B05AIPS_CDDOWNLOAD_IBDE_UNC=\\%%B05AIPS_UPLOAD_NODE.\F$\DATA\IPSL\CDFILES\B05_NAG\CD\INCOMING %%B05AIPS_CDDOWNLOAD_FTS_UNC=\\%%B05AIPS_UPLOAD_NODE.\B05_NAG\FTS\To_Clearpath\%%DATE
%%B05AIPS_CDDOWNLOAD_IBDE_UNC=\\%%B05AIPS_UPLOAD_NODE.\F$\DATA\IPSL\CDFILES\B05_NAG\CD\INCOMING
%%B05AIPS_CDDOWNLOAD_FTS_UNC=\\%%B05AIPS_UPLOAD_NODE.\B05_NAG\FTS\To_Clearpath\%%DATE_CCYYMMDD.
%%B05AIPS_CDDOWNLOAD_FTS_UNC=%%B05AIPS_CDDOWNLOAD_FTS_UNC.
我得到了大约30多个不同的文本文件,其中包含上述类型的条目,并希望删除重复行,并希望保留第一次出现。请记住,重复的行只应在“=”号之前标识,整个行需要删除。每个不同的文本文件都有“%%”号。请指导我,如果有办法通过批处理脚本或vbscript?谢谢您可以将文件读入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
个人作品的代码应该很容易在网上找到。请务必要求提供您可能需要的任何其他特定指针。您可以将文件读入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
个人作品的代码应该很容易在网上找到。请务必询问您可能需要的任何其他、具体的指针。这里有一个简单的解决方案;让我们调用脚本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
脚本基于这样一个事实,即不能出现名称相同的重复环境变量
此代码仅在满足以下条件时有效:
- 以不区分大小写的方式处理文件内容李>
- 输出文件中的行顺序无关紧要李>
- 第一个
符号前的部分字符串以=
开头,并至少包含一个除%%
以外的字符李>%%
- 第一个
前面的部分字符串只包含可能出现在环境变量名称中的字符,除了前导的=
李>%%
- 第一个
后面的部分字符串不能为空李>=
- 第一个
后面的部分字符串不能单独以=
开头李>=
- 没有感叹号
允许在文件中使用code>,因为它们可能会丢失或导致其他意外结果李>
以下是使用临时文件的替代方法:
@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
保留到第一个=
符号的每个唯一(非空)标记都会写入一个临时文件,在从输入文件中读取每一行后对其进行搜索。如果令牌在临时文件中已经可用,则跳过该行;如果不是,则将其写入输出文件
除非从findstr
命令中删除/I
开关,否则将以不区分大小写的方式处理文件内容
更新:改进的脚本 下面是两个经过改进的脚本,没有特殊角色会导致它们失败。他们不使用临时文件。两个脚本都会删除包含重复关键字的行(例如第一个
=
符号前的部分字符串)
如果遇到重复的关键字,此脚本将保留第一行:
@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
@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
如果遇到重复的关键字,此脚本将保留最后一行:
@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
@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
对于这两个脚本,以下规则适用:
- 保持关键字不重复的行的顺序李>
- 空行被忽略,因此被删除李>
- 空关键字表示以
开头的行被忽略,因此被删除李>=
- 对于根本不包含
的非空行,将其视为以=
结尾以检查重复项,因此整行用作关键字李>=
- 对于检查重复项,每个制表符都被一个空格替换李>
- 传输到返回文件的每一行都是从原始文件复制而来的,没有任何更改(因此前面提到的
附件或TAB的替换没有反映在这里)李>=
- 重复项的检查以不区分大小写的方式进行,除非从
命令中删除findstr
开关李>/I
修正:处理多个文件 以上所有脚本都是为处理单个文件而设计的。但是,如果需要处理多个文件,只需编写一个包装器,其中包含一个
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=\u no-dups”
)。覆盖原始输入文件的命令行是:move/Y“D:\Data\target\*.*”D:\Data\source“
以下是一个简单的解决方案;让我们调用脚本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
脚本基于这样一个事实,即不能出现名称相同的重复环境变量
<