wake-up-neo.com

Wie zählt man keine Zeilen in einer Textdatei und speichert den Wert mittels Batch-Skript in einer Variablen?

Ich möchte die Zeilenanzahl in einer Textdatei zählen und dann muss der Wert in einer Umgebungsvariablen gespeichert werden. Der Befehl, die Anzahl der Zeilen zu zählen, lautet

 findstr/R/N "^" file.txt | find/C ":" 

Ich verwies auf die Frage Wie kann ich das Ergebnis eines Befehlsausdrucks mithilfe von bat-Skripts in einer Variablen speichern? Dann habe ich versucht,

 set cmd = "findstr/R/N" ^ "file.txt | find/C": "" 

Ich erhalte die Fehlermeldung,

 FIND: Parameterformat nicht korrekt 

Wie könnte ich diesen Fehler beseitigen? 

45
rashok

Sie können die FOR/F-Schleife verwenden, um die Ausgabe einer Variablen zuzuweisen. 

Ich benutze den cmd-variable, es ist also nicht notwendig, die Pipe oder andere Zeichen in der cmd-Zeichenfolge zu umgehen, da die verzögerte Erweiterung die Zeichenfolge "unverändert" an die FOR-Schleife übergibt.

@echo off
cls
setlocal EnableDelayedExpansion
set "cmd=findstr /R /N "^^" file.txt | find /C ":""

for /f %%a in ('!cmd!') do set number=%%a
echo %number%
33
jeb

Es gibt einen viel einfacheren Weg als alle anderen Methoden.

find /v /c "" filename.ext

Offensichtlich von den alten MS-DOS-Tagen. Weitere Informationen hier: http://blogs.msdn.com/b/oldnewthing/archive/2011/08/25/10200026.aspx

Anwendungsbeispiel:

adb Shell pm list packages | find /v /c ""

Wenn Ihr Android-Gerät mit Ihrem PC verbunden ist und sich das Android SDK im Pfad befindet, wird die Anzahl der auf Ihrem Gerät installierten Apps ausgedruckt.

84
user169771

Inspiriert von den vorherigen Beiträgen, ist .__ ein kürzerer Weg, dies zu tun:

CMD.exe
C:\>FINDSTR /R /N "^.*$" file.txt | FIND /C ":"

Die Anzahl der Zeilen

Versuch es. Es funktioniert in meiner Konsole.

BEARBEITET:

(das "$" Zeichen wurde entfernt)

FINDSTR /R /N "^.*" file.txt | FIND /C ":"

$ reduziert die Anzahl um 1, da die erste Zeile als Feldname akzeptiert und dann die Anzahl der Zeilen gezählt wird.

16
Tin Amaranth

Versuche dies:

@Echo off
Set _File=file.txt
Set /a _Lines=0
For /f %%j in ('Find "" /v /c ^< %_File%') Do Set /a _Lines=%%j
Echo %_File% has %_Lines% lines.

Es entfällt das zusätzliche FindStr und muss nicht erweitert werden.


- bearbeitet, um den Weiterleitungsvorschlag von ChrisJJ zu verwenden. Durch das Entfernen des Befehls TYPE wird es dreimal schneller.

8
Tony

Normalerweise benutze ich etwas ähnliches for /f %%a in (%_file%) do (set /a Lines+=1)

4
Ray

@ Tony: Sie können sogar den Befehl type %file% loswerden.

for /f "tokens=2 delims=:" %%a in ('find /c /v "" %_file%') do set /a _Lines=%%a

Bei langen Dateien sollte dies noch schneller sein.

4
Dazzam

Sie müssen nicht find verwenden.

@echo off
set /a counter=0
for /f %%a in (filename) do set /a counter+=1
echo Number of lines: %counter%

Dadurch werden alle Zeilen in der Datei durchlaufen und die Zählervariable für jede Zeile um 1 erhöht.

3
Andreas Mångs
 für/f "usebackq"% A in (`TYPE c:\temp\file.txt ^ | find/v/c" ")) setze numlines =% A

verwenden Sie in einer Batchdatei %% A anstelle von% A

2
Tom Warfield

Ich fand diese Lösung am besten zum Erstellen einer Protokolldatei, die sich selbst verwaltet:

setlocal enabledelayedexpansion
SET /A maxlines= 10
set "cmd=findstr /R /N "^^" "filename.txt" | find /C ":""
 for /f %%a in ('!cmd!') do set linecount=%%a
GOTO NEXT

:NEXT 
 FOR /F %%A IN ("filename.txt") DO ( 
  IF %linecount% GEQ %maxlines% GOTO ExitLoop
  echo %clientname% %Date% %Time% >> "filename.txt")
 EXIT

:ExitLoop
 echo %clientname% %Date% %Time% > "filename.txt"
 EXIT

Umgebungsvariablen sind% clientname% der Computername des Remote-Clients.% Date% ist das aktuelle Datum und% Time% die aktuelle Uhrzeit. : NEXT wird aufgerufen, nachdem die Anzahl der Zeilen in der Datei abgerufen wurde. Wenn die Anzahl der Dateizeilen größer als die Variable% maxlines% ist, wird zu: EXITLOOP weitergeleitet, wo die Datei überschrieben wird, wobei eine neue Zeile mit der ersten Informationszeile erstellt wird. Wenn es weniger als die Variable% maxlines% ist, wird die Zeile einfach zur aktuellen Datei hinzugefügt. 

2
joopykunk

Gerade:

c:\>(for /r %f in (*.Java) do @type %f ) | find /c /v ""

Font: https://superuser.com/questions/959036/what-is-the-windows-equivalent-of-wc-l

1
Carlos.Cândido

Sie können die Ausgabe von type in find innerhalb der in(…)-Klausel einer for /f-Schleife leiten:

for /f %%A in ('
    type "%~dpf1" ^| find /c /v ""
') do set "lineCount=%%A"

Aber die Pfeife startet eine Subshell, was die Sache verlangsamt.

Oder Sie können die Eingabe aus der Datei in find umleiten, wie folgt:

for /f %%A in ('
    find /c /v "" ^< "%~dpf1"
') do set "lineCount=%%A"

Dieser Ansatz gibt Ihnen jedoch eine Antwort 1 weniger als die tatsächliche Anzahl von Zeilen, wenn die Datei mit einer oder mehreren leeren Zeilen endet, wie von den späten foxidrive in Zählzeilen in einer Datei hervorgehoben.

Und dann könnten Sie immer noch versuchen:

find /c /v "" example.txt

Das Problem ist, die Ausgabe des obigen Befehls sieht folgendermaßen aus:

---------- EXAMPLE.TXT: 511

Sie können die Zeichenfolge im Doppelpunkt aufteilen, um die Anzahl zu ermitteln. Es kann jedoch mehr als ein Doppelpunkt geben, wenn der Dateiname einen vollständigen Pfad enthält.

Hier ist meine Meinung zu diesem Problem:

for /f "delims=" %%A in ('
    find /c /v "" "%~1"
') do for %%B in (%%A) do set "lineCount=%%B"

Dadurch wird immer die Anzahl in der Variablen gespeichert.

Nur ein letztes kleines Problem… find behandelt Nullzeichen als Zeilenumbrüche. Wenn sich also hinterlistige Nullen in Ihre Textdatei eingeschlichen haben oder Sie die Zeilen in einer Unicode-Datei zählen möchten, ist diese Antwort nicht für Sie.

0
Sponge Belly

Im folgenden Code sind der Variablenname SalaryCount und TaxCount

@ECHO OFF    
echo Process started, please wait...    
for /f %%C in ('Find /V /C "" ^< "D:\Trial\Salary.txt"') do set SalaryCount=%%C    
echo Salary,%SalaryCount%
for /f %%C in ('Find /V /C "" ^< "D:\Trial\Tax.txt"') do set TaxCount=%%C
echo Tax,%TaxCount%

Wenn Sie diese Werte nun in eine CSV-Datei ausgeben müssen, können Sie den folgenden Code verwenden.

@ECHO OFF
cd "D:\CSVOutputPath\"
echo Process started, please wait...
echo FILENAME,FILECOUNT> SUMMARY.csv
for /f %%C in ('Find /V /C "" ^< "D:\Trial\Salary.txt"') do set Count=%%C
echo Salary,%Count%>> SUMMARY.csv
for /f %%C in ('Find /V /C "" ^< "D:\Trial\Tax.txt"') do set Count=%%C
echo Tax,%Count%>> SUMMARY.csv

Der > überschreibt den vorhandenen Inhalt der Datei und der >> fügt die neuen Daten an die vorhandenen Daten an. Die CSV wird in D:\CSVOutputPath generiert.

0
Sarath Avanavu

Die folgende :countLines-Subroutine akzeptiert zwei Parameter: einen Variablennamen; und einen Dateinamen. Die Anzahl der Zeilen in der Datei wird gezählt, das Ergebnis wird in der Variablen gespeichert und das Ergebnis wird an das Hauptprogramm zurückgegeben.

Der Code verfügt über folgende Funktionen:

  • Liest Dateien mit Windows- oder Unix-Zeilenenden.
  • Verarbeitet Unicode- sowie ANSI/ASCII-Textdateien.
  • Bewältigt extrem lange Linien.
  • Wird nicht durch das Nullzeichen verwirrt.
  • Löst beim Lesen einer leeren Datei einen Fehler aus.
  • Zählt jenseits des Batch-Max-Int-Grenzwerts von (31^2)-1.
@echo off & setLocal enableExtensions disableDelayedExpansion

call :countLines noOfLines "%~1" || (
    >&2 echo(file "%~nx1" is empty & goto end
) %= cond exec =%
echo(file "%~nx1" has %noOfLines% line(s)

:end - exit program with appropriate errorLevel
endLocal & goto :EOF

:countLines result= "%file%"
:: counts the number of lines in a file
setLocal disableDelayedExpansion
(set "lc=0" & call)

for /f "delims=:" %%N in ('
    cmd /d /a /c type "%~2" ^^^& ^<nul set /p "=#" ^| (^
    2^>nul findStr /n "^" ^&^& echo(^) ^| ^
    findStr /blv 1: ^| 2^>nul findStr /lnxc:" "
') do (set "lc=%%N" & call;) %= for /f =%

endlocal & set "%1=%lc%"
exit /b %errorLevel% %= countLines =%

Ich weiß, dass es abscheulich aussieht, aber es deckt die meisten Edge-Fälle ab und ist überraschend schnell.

0
Sponge Belly