Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/batch-file/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Batch file 如何使用批处理脚本或vb脚本从文本文件中删除重复条目?_Batch File_Vbscript - Fatal编程技术网

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
脚本基于这样一个事实,即不能出现名称相同的重复环境变量

此代码仅在满足以下条件时有效:

  • 以不区分大小写的方式处理文件内容
  • 输出文件中的行顺序无关紧要
  • 第一个
    =
    符号前的部分字符串以
    %%
    开头,并至少包含一个除
    %%
    以外的字符
  • 第一个
    =
    前面的部分字符串只包含可能出现在环境变量名称中的字符,除了前导的
    %%
  • 第一个
    =
    后面的部分字符串不能为空
  • 第一个
    =
    后面的部分字符串不能单独以
    =
    开头
  • 没有感叹号
    ,因为它们可能会丢失或导致其他意外结果
    

以下是使用临时文件的替代方法:

@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
脚本基于这样一个事实,即不能出现名称相同的重复环境变量

<