2013-04-05 232 views
2

我试图在记事本++中进行批处理,它将计算所选文本中重复行的数量。通过文件循环批处理

到目前为止,我有记事本+做工精细

NPE_CONSOLE v+ 
CLS 
ECHO $(CURRENT_WORD) 
CON_SAVETO "H:\tmp.txt" 
NPE_CONSOLE v- 

该脚本将所选文本tmp.txt,唯一的问题是,它包括,在底部,CON_SAVETO "H:\tmp.txt"但我可以忍受现在。

编辑另外,我不认为Notepad ++是这里的问题,因为我尝试从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% 
) 

我用尽了一切我能想到的,包括分裂断过程变成一个功能,但我不断收到类似错误Unexpected),或者如果它运行,它不循环通过该文件。

目前,这是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 
+0

您是否认为记事本++会导致此行为? – Endoro 2013-04-05 18:29:10

+0

我不认为记事本+ +是这里的问题,尽管我包含代码以防有人可以确认或否认。更新问题以更好地解释这一点。 – 2013-04-05 18:30:55

+0

你怎样称呼你的批处理文件(以及你传入的参数);即在这个例子中'%1'解析了什么? – 2013-04-05 18:53:39

回答

4
@ECHO OFF 
SETLOCAL enabledelayedexpansion 
FOR %%i IN (prev) DO SET "%%i=" 
FOR /f "delims=" %%i IN ('sort ^<temp.txt') DO (
IF DEFINED prev (
    IF "!prev!"=="%%i" (SET /a count+=1) ELSE (
    ECHO !prev! - !count! 
    SET "prev=" 
) 
) 
IF NOT DEFINED prev (
    SET prev=%%i 
    SET /a count=1 
) 
) 
ECHO %prev% - %count% 

这里是我的版本。对输入文件进行排序,像线一样组合在一起,然后当行内容发生变化时,显示前一个内容并对前一行的计数器和记录进行计数和重置。

+0

+1使用'sort'的好主意。这比我的解决方案更有效率(http://stackoverflow.com/a/15842198/1683264)我想。它不会保持顺序。不确定这是否重要。 – rojo 2013-04-05 19:43:05

+0

不错++! \t @@@@@@@@@@@@@ – Endoro 2013-04-05 20:07:20

+0

当它几乎是复制粘贴解决方案时就喜欢它。 (必须将'temp'改为'tmp'并重新插入'CD'),但是太棒了。像魔术一样工作。 – 2013-04-05 20:38:01

2

不能设置环境变量和使用%语法相同for循环中使用它,你需要使用延迟扩展并使用!语法。

我没有测试过这一点,但试试这个:

::@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循环体为子程序。

0

你犯了更多的错误,我现在告诉你。看看delayed expansionif /?for /?set /?和所有批次的东西...

@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!" 
) 

您的代码是没有意义的,如果你正确地postet的tmp.txt内容。

+0

“如果您正确填写了'tmp.txt'的内容,您的代码就没有意义了。”这个评论是无用的,因为它没有解释什么是错的,也没有解释为什么它是错的。 – 2013-04-05 20:39:59

+0

对不起,但是你的批量知识太差了,生活很短暂。 – Endoro 2013-04-05 20:48:24

1

这是我对一个不同的方向的想法。它输出你期望的结果。输出不排序;线的原始顺序保持不变。

@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]!" 
) 
3

下面的批处理程序你更快的方式想要什么,只要行不包含某些特殊字符批:

@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 
) 
+0

我想过这个,但任何包含[] =的行都会导致意想不到的结果。由于这是为了与Notepad ++的宏配合使用的,因此在选择的文本中将会有编程符号,他会检查重复的行。不过,伟大的头脑+1也是如此。 – rojo 2013-04-05 20:24:45

+0

我只是做了一个小修复,允许行中的任何内容,除了特殊的批处理字符,如感叹号 – Aacini 2013-04-05 20:29:27

3

我要给你一个不同的,但简单的解决方案。您可以下载GNU utilities for win32。然后只是提取它。它是用于Windows的移植工具的集合。非常便利。

然后从那里使用sortuniq程序。你可以发现他们在

extracted_folder\usr\local\wbin\ 

那么你可以只是简单的从窗户command line

sort original_file.txt | uniq --count > count.txt 

。你会发现你在count.txt


需要什么请确保您有路径正确,或你有你的path提取的文件夹中。如果不在路径上,请执行如下操作:

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

+1迄今为止发布的6个答案中,这是最有效率的,也是唯一不应该出现的问题在检查的内容中​​是否存在特殊字符。 unixutils和gnuwin32使Windows脚本更容易。 – rojo 2013-04-05 20:31:52

+0

+1,我印象深刻的是,您意识到您必须使用GNU'sort'工具,而不是本机Windows'sort'工具。愚蠢的Windows'sort'不区分大小写:-( – dbenham 2013-04-06 13:31:06