Batch file 批处理循环文件

Batch file 批处理循环文件,batch-file,notepad++,Batch File,Notepad++,我试图在记事本++中创建一个批处理过程,该过程将计算所选文本的重复行数 到目前为止,我的记事本++工作良好 NPE_CONSOLE v+ CLS ECHO $(CURRENT_WORD) CON_SAVETO "H:\tmp.txt" NPE_CONSOLE v- 此脚本将所选文本保存到tmp.txt中,唯一的问题是它在底部包括CON\u SAVETO“H:\tmp.txt”,但我现在可以接受它 EDIT:另外,我不认为记事本++是问题所在,因为我尝试从cmd行运行批处理文件,并得到相同的错误

我试图在记事本++中创建一个批处理过程,该过程将计算所选文本的重复行数

到目前为止,我的记事本++工作良好

NPE_CONSOLE v+
CLS
ECHO $(CURRENT_WORD)
CON_SAVETO "H:\tmp.txt"
NPE_CONSOLE v-
此脚本将所选文本保存到
tmp.txt
中,唯一的问题是它在底部包括
CON\u SAVETO“H:\tmp.txt”
,但我现在可以接受它


EDIT:另外,我不认为记事本++是问题所在,因为我尝试从
cmd
行运行批处理文件,并得到相同的错误/问题。我还尝试手动设置
tmp.txt
文件,但仍然存在相同的问题

我的批处理文件是导致问题的原因:

::@ECHO OFF
CD "H:\"
SET counter=0
SET prev=a

FOR /F "tokens=*" %%L IN (tmp.txt) DO (
    SET blnOut=0
    SET curLine="%%L"

    IF /I %prev%==%curLine% (
        SET counter=%counter%+1
        SET blnOut=1
    )
    IF %blnOut%==0 (
        IF %prev%==a (
            SET counter=%counter%+1
            SET blnOut=1
        )
        IF %blnOut%==0 (
            ECHO %curLine%- %counter%
            SET counter=1
        )
    )
    SET prev=%curLine%
)
我已经尝试了所有我能想到的方法,包括将进程拆分为函数,但我总是会遇到错误,例如
意外)
或者,如果它确实运行,它不会在文件中循环

目前,这是
tmp.txt

1
2
3
4
5
6
7
8
1
4
5
8
4
3
4
4
5
所以理想的输出是:

1 - 2
2 - 1
3 - 2
4 - 5
5 - 3
6 - 1
7 - 1
8 - 2

您不能使用
%
语法设置环境变量并在相同的
循环中使用它,您需要使用延迟扩展并使用
语法

我还没有测试过这个,但是试试这个:

::@ECHO OFF
SETLOCAL ENABLEDELAYEDEXPANSION
CD "H:\"
SET counter=0
SET prev=a

FOR /F "tokens=*" %%L IN (tmp.txt) DO (
    SET blnOut=0
    SET curLine="%%L"

    IF /I !prev!==!curLine! (
        SET counter=!counter!+1
        SET blnOut=1
    )
    IF !blnOut!==0 (
        IF !prev!==a (
            SET counter=!counter!+1
            SET blnOut=1
        )
        IF !blnOut!==0 (
            ECHO !curLine!- !counter!
            SET counter=1
        )
    )
    SET prev=!curLine!
)

或者将
for
循环的主体移动到一个子例程中。

我现在就告诉你,你犯了更多错误。查看
延迟扩展
如果/?
为/?
设置/?
以及所有批处理内容

@ECHO OFF &setlocal enabledelayedexpansion
CD /d "H:\"
SET counter=0
SET prev=a

FOR /F "tokens=*" %%L IN (tmp.txt) DO (
    SET blnOut=0
    SET "curLine=%%L"

    IF /I "!prev!"=="!curLine!" (
        SET /a counter+=1
        SET blnOut=1
    )
    IF "!blnOut!"=="0" (
        IF "!prev!"=="a" (
            SET /a counter+=1
            SET blnOut=1
        )
        IF "!lnOut!"=="0" (
            ECHO !curLine!- !counter!
            SET counter=1
        )
    )
    SET "prev=!curLine!"
)

如果您正确地发布了
tmp.txt
的内容,那么您的代码就没有意义了。

以下是我的想法,希望有一点不同的方向。它输出您期望的结果。输出未排序;将保持行的原始顺序

@ECHO OFF
setlocal enabledelayedexpansion

set filename=h:\tmp.txt
set idx=0

:: build array of unique lines
FOR /F "usebackq delims=" %%I IN ("%filename%") DO (

    rem :: if dupe line not already processed
    2>NUL set line | findstr /r /c:"^line\[[0-9]*\]=%%I$" >NUL || (

        rem :: add it to the array
        set "line[!idx!]=%%I"
        set /a "idx+=1"
    )
)

:: For each unique line
set /a "idx-=1"
for /L %%I in (0,1,%idx%) do (

    rem :: Echo the line contents without a line break
    set /p "=!line[%%I]! - "<NUL

    rem :: use find /c to count the instances of that line.
    findstr /b /e /c:"!line[%%I]!" "%filename%" | find /c "!line[%%I]!"
)
@ECHO关闭
延迟扩展
设置文件名=h:\tmp.txt
设置idx=0
::生成唯一行的数组
对于/F“usebackq delims=“%%I IN”(“%filename%”)DO(
rem::如果尚未处理重复行
2> NUL集合行| findstr/r/c:“^line\[[0-9]*\]=%%I$”>NUL |(
rem::将其添加到数组中
设置“行[!idx!]=%%I”
设置/a“idx+=1”
)
)
::对于每个唯一的行
设置/a“idx-=1”
对于(0,1,%idx%)中的/L%%I,请执行以下操作(
rem::回显行内容而不断行
设置/p“=!行[%%I]!-”
@ECHO OFF
SETLOCAL enabledelayedexpansion
对于(上一个)中的%%i,请设置“%%i=”

对于/f“delims=“%%i IN('sort^以下批处理程序,只要行不包含某些特殊的批处理字符,就可以更快地执行您想要的操作:

@echo off
setlocal EnableDelayedExpansion
for /F "delims=" %%a in (tmp.txt) do (
   set /A "line[%%a]+=1"
)
for /F "tokens=2* delims=[]=" %%a in ('set line[') do (
   echo %%a - %%b
)

我有一个不同但更简单的解决方案

你可以下载。然后解压缩它。这是一个Windows移植工具的集合。非常方便

然后使用
sort
uniq
程序。您可以在

extracted_folder\usr\local\wbin\
那你就可以简单地做了

sort original_file.txt | uniq --count > count.txt
从windows
命令行
。您将在
count.txt


确保路径正确,或者在
路径中有提取的文件夹。如果不在路径中,请执行以下操作

"C:\GNUWin_standalone\usr\local\wbin\sort.exe" original_file.txt | "C:\GNUWin_standalone\usr\local\wbin\uniq.exe" --count > count.txt

你认为记事本++会导致这种行为吗?我不认为记事本++是这里的问题,尽管我包含了代码,以防有人可以确认或否认。更新了问题以更好地解释这一点。如何调用批处理文件(以及传递了哪些参数);即,
%1
在本例中解析为什么?我的坏,
%1
是在我作为单独的函数尝试时留下的。没有传递给它的参数,只需使用完整路径(
“H:\scripts\UniqueLine.bat”
)即可调用它这里需要使用批处理文件吗?或者它可以是任何类型的脚本吗?正如您所写的,逻辑似乎只会找到相同的连续行,而不会找到在其他地方重复的行。批处理这种事情(顺便说一句,这是一种糟糕的编程语言)这将是非常困难的。使用Perl之类的东西会很简单。+1使用
排序
的好主意。这比我想象的更有效。但它不会保持行的有序。不确定这是否重要。当它几乎是复制粘贴解决方案时,我喜欢它。(必须将
temp
更改为
tmp
并重新插入
CD
)但效果非常好。效果非常神奇。@DavidStarkey-这个答案存在潜在的问题:它可以处理数字,但可能无法处理alpha和符号,原因有两个:1)排序不区分大小写。如果不关心大小写,请使用
If/I“!prev!”=“%%i”
以获得不区分大小写的正确答案。2)延迟扩展将损坏
%%i
的值(如果它包含
)。这可以通过切换延迟扩展的开和关来解决,注意根据需要保留ENDLOCAL屏障上的值。我考虑过这一点,但任何包含[]=将导致意外结果。由于这是用于记事本++的宏,因此在所选文本中会有编程符号,他正在检查是否有重复行。+1表示伟大的思想相似。我只是做了一个小修复,允许行中有任何内容,但特殊的批处理字符除外在目前发布的6个答案中,ke感叹号+1是最有效的,也是唯一一个在检查内容中是否存在任何特殊字符都不重要的答案。unixutils和gnuwin32使Windows脚本编写变得更加简单。+1,您认识到必须使用GNU
排序
实用程序,而不是本机Windows
sort
实用程序。愚蠢的Windows
sort
不区分大小写:-(“如果您正确地发布了
tmp.txt
的内容,那么您的代码就没有意义了。”此评论没有帮助,因为它无法解释错误的原因和原因。抱歉,但是您的批处理知识太贫乏,寿命很短。
"C:\GNUWin_standalone\usr\local\wbin\sort.exe" original_file.txt | "C:\GNUWin_standalone\usr\local\wbin\uniq.exe" --count > count.txt