Powershell 批处理以仅从字符串中删除重复的段

Powershell 批处理以仅从字符串中删除重复的段,powershell,batch-file,cmd,Powershell,Batch File,Cmd,batch/powershell中有一个快速脚本或命令,用于仅分析txt文件所有行中的重复段和可变段并将其删除?例如: 输入文件1.txt: abcde11234452232131 abcde6176413190830 abcde6278647822786 abcde676122249819113 11234452232131 6176413190830 6278647822786 676122249819113 输出文件1.txt: abcde11234452232131 abcde617

batch/powershell中有一个快速脚本或命令,用于仅分析txt文件所有行中的重复段和可变段并将其删除?例如:

输入文件1.txt:

abcde11234452232131
abcde6176413190830
abcde6278647822786
abcde676122249819113
11234452232131
6176413190830
6278647822786
676122249819113
输出文件1.txt:

abcde11234452232131
abcde6176413190830
abcde6278647822786
abcde676122249819113
11234452232131
6176413190830
6278647822786
676122249819113
输入文件2.txt:

11234452232131xyz
6176413190830xyz
6278647822786xyz
676122249819113xyz
11234452232131
6176413190830
6278647822786
676122249819113
输出文件2.txt:

11234452232131xyz
6176413190830xyz
6278647822786xyz
676122249819113xyz
11234452232131
6176413190830
6278647822786
676122249819113
我的剧本:

@echo off & setlocal enabledelayedexpansion

:startline

set /p first=<#SHA1.txt

set status=notequal

for /f "delims=" %%a in (#SHA1.txt) do (
set second=%%a
if "!first:~0,1!"=="!second:~0,1!" (set status=equal) else (set status=notequal & goto break)
)

if "!status!"=="equal" (
for /f "delims=" %%a in (#SHA1.txt) do (
set second=%%a
echo !second:~1!>>#SHA1.tmp
)
if exist #SHA1.tmp (del #SHA1.txt & ren #SHA1.tmp #SHA1.txt)
goto startline
)

:break

:endline

set /p first=<#SHA1.txt

set status=notequal

for /f "delims=" %%a in (#SHA1.txt) do (
set second=%%a
if "!first:~-1!"=="!second:~-1!" (set status=equal) else (set status=notequal & goto break)
)

if "!status!"=="equal" (
for /f "delims=" %%a in (#SHA1.txt) do (
set second=%%a
echo !second:~0,-1!>>#SHA1.tmp
)
if exist #SHA1.tmp (del #SHA1.txt & ren #SHA1.tmp #SHA1.txt)
goto endline
)

:break

exit
@echo off&setlocal enabledelayedexpansion
:斯达林
set/p first=>SHA1.tmp
)
如果存在#SHA1.tmp(del#SHA1.txt和ren#SHA1.tmp#SHA1.txt)
跳跳
)
:休息
:结束行
set/p first=>SHA1.tmp
)
如果存在#SHA1.tmp(del#SHA1.txt和ren#SHA1.tmp#SHA1.txt)
转到终点线
)
:休息
出口
我认为这个脚本在多个文件中运行很慢。

这是怎么回事(请参阅解释性的
注释):

@echo关闭
::此脚本假定输入文件的行(作为命令行参数提供)
::不包含任何字符`^`、`!`、,和``。线条可能不同
::长度,但忽略空行。
::脚本分两个阶段处理输入文件:
当前位置1.我们称之为分析阶段,包括以下步骤:
:*读取文件的第一行,存储字符串并确定其长度;
:*阅读第二行,从左到右遍历所有字符
::在同一循环的右侧,找到指向
::最左边的第一个字符和最右边的最后一个字符不等于各自的
::从第一行开始的字符串中的,并存储检索的索引;
读剩下的几行,并为每一行提取所需的前缀和后缀
::由各自存储的索引指示,并将其与各自的
::第一行的前缀和后缀;如果两者相等,则在此处退出循环
::并继续下一行;否则,遍历所有以开头的字符
::在前一个最左侧字符索引之前和前一个最右侧字符索引之后
::在字符串的各个末端,找到再次显示的字符索引
::指向不相等的最左边的第一个字符和最右边的最后一个字符
::从第一行开始的字符串中的相应值,并更新先前的
::相应地存储索引;
::2.让我们称之为执行阶段,再次读取输入文件,提取
::由两个计算索引指示并返回的每行的部分;
::输出显示在控制台中;要将其写入文件,请使用重定向(`>`)。
setlocal EnableDelayedExpansion
设置“最小值=“&set”最大值=“&set/A”行=0”
对于/F usebackq^delims^=^eol^=%%L in(“%1”)do(
设置/A“行+=1”和设置“STR=%%L”
如果!行!相等1(
调用:长度LEN“%%L”
设置“SAV=%%L”
)否则,如果!行!相等2(
设置/A“IDX=LEN-1”
对于(0,1,!IDX!)中的/L%%I,请执行以下操作(
如果未定义最小值(
如果不是“!STR:~%I,1!”==”!SAV:~%I,1!”设置/A“MIN=%I”
)
如果未定义最大值(
设置/A“IDX=%%I+1”
对于%%J英寸(!IDX!),请执行以下操作(
如果不是“!STR:~-%%J,1!”==”!SAV:~-%%J,1!”设置/A“MAX=1-%%J”
)
)
)
如果未定义最小值集/A“最小值=最小值,最大值=最小值”
)否则(
设置“NXT=#”
如果(!MIN!)中%%I的!MIN!gtr 0不存在,则执行“!STR:~,%%I!”=”!SAV:~,%%I!”设置“NXT=”
如果(!MAX!)中%%J的!MAX!lss为0,则不执行“!STR:~%%J!”==”!SAV:~%%J!”设置“NXT=”
如果未定义NXT(
如果!MAX!lss-!MIN!(设置/A“IDX=1-MAX”)否则(设置/A“IDX=MIN-1”)
对于(!IDX!,-1,0)do中的/L%%I(
如果%%I lss!MIN(
如果不是“!STR:~%I,1!”==”!SAV:~%I,1!”设置/A“MIN=%I”
)
如果-%%I geq!MAX(
设置/A“IDX=%%I+1”
对于%%J英寸(!IDX!),请执行以下操作(
如果不是“!STR:~-%%J,1!”==”!SAV:~-%%J,1!”设置/A“MAX=1-%%J”
)
)
)
)
)
)
如果定义了MAX if!MAX!eq 0设置“MAX=8192”
对于/F“令牌=1,2”%%I in(“%MIN%%MAX%”)do(
对于/F usebackq^delims^=^eol^=%%L in(“%1”)do(
设置“STR=%%L”
回声(!STR:~%%I,%%J!
)
)
端部
退出/B
:长度
::用于确定字符串长度的函数。
::参数:
::用于接收结果字符串长度的变量;
::用于确定长度的字符串值;
设置“STR=%~2”
setlocal EnableDelayedExpansion
设置/A“长度=1”
如果定义STR(
对于%%C in(4096 2048 1024 512 256 128 64 32 16 8 4 2 1),请执行以下操作(
如果不是“!STR:~%%C!”==”集/A“LEN+=%%C”&集“STR=!STR:~%%C!”
)
)否则设置/A“LEN=0”
endlocal&设置“%~1=%LEN%”
退出/B
这可能会进一步改进,这也取决于数据:

  • 如果第一行的长度是固定的,或者行的长度在一个很小的范围内变化,您可以避免
    :length
    子例程调用,而是使用一个常量值;如果公共前缀/后缀有一个已知的最大长度,那么甚至根本不需要行的长度
  • 您可以在开始时将文件读入内存,以后再使用这些数据,而不是两次读取文件(由于采用了双通道算法);但是对于大型文件,这可能是一个坏主意
  • 我使用了几个
    for/L
    循环遍历特定字符范围,由于
    循环或类似
    exit for
    的情况下缺少
    ,因此一些
    if
    条件跳过了这些循环的主体;我可以使用
    goto
    将它们保留下来,但我需要将这些循环放在单独的子例程中以避免中断外部循环;无论如何,[/L]
    循环在后台完成迭代,即使被
    goto
    打断,但速度比执行主体快;因此与缓慢的
    调用
    gotoabcde11234452232131
    abcde6176413190830
    abcde6278647822786
    abcde676122249819113
    
    11234452232131
    6176413190830
    6278647822786
    676122249819113
    
    11234452232131xyz
    6176413190830xyz
    6278647822786xyz
    676122249819113xyz
    
    11234452232131
    6176413190830
    6278647822786
    676122249819113
    
    abcde11234452232131
    6176abcde4131908abcde30
    6278647abcde822786
    676122249819113abcde
    
    11234452232131
    6176413190830
    6278647822786
    676122249819113