2013-04-05 290 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