Per Batch zeilenweise Zeichen Zählen
Hallo zusammen,
ich habe mich schon doof gegoogled und brauche mal Eure Hilfe.
Also, ich möchte eine Batch-Datei schreiben, welche in einer ASC-Datei die Anzahl eines bestimmten Zeichens ';' pro Zeile zählt und mir die Zeile(n) ausgibt, wo das Zeichen mehr als x mal vorkommt.
Habe leider nichts für mich verständliches zum Thema "delims" und for... und zu dem Gesamtproblem gefunden.
Mit -> findstr /n /b /R ";" Test.txt kann ich immerhin schonmal die Semikolons rauslesen. Aber wie zähle ich die im Batch Zeilenweise und gebe Sie dann Anzahl-abhängig aus?
Kann mir jemand helfen und vielleicht auch mal die ominöse Syntax von delims erklären?
Tausend Dank schonmal!
Gruss
Ralf
ich habe mich schon doof gegoogled und brauche mal Eure Hilfe.
Also, ich möchte eine Batch-Datei schreiben, welche in einer ASC-Datei die Anzahl eines bestimmten Zeichens ';' pro Zeile zählt und mir die Zeile(n) ausgibt, wo das Zeichen mehr als x mal vorkommt.
Habe leider nichts für mich verständliches zum Thema "delims" und for... und zu dem Gesamtproblem gefunden.
Mit -> findstr /n /b /R ";" Test.txt kann ich immerhin schonmal die Semikolons rauslesen. Aber wie zähle ich die im Batch Zeilenweise und gebe Sie dann Anzahl-abhängig aus?
Kann mir jemand helfen und vielleicht auch mal die ominöse Syntax von delims erklären?
Tausend Dank schonmal!
Gruss
Ralf
Bitte markiere auch die Kommentare, die zur Lösung des Beitrags beigetragen haben
Content-ID: 103571
Url: https://administrator.de/forum/per-batch-zeilenweise-zeichen-zaehlen-103571.html
Ausgedruckt am: 16.05.2025 um 08:05 Uhr
8 Kommentare
Neuester Kommentar
Hallo marlasdad und willkommen im Forum!
Vielleicht holst Du etwas weiter aus und beschreibst eine solche Zeile näher (bzw postest ein Beispiel) - aufgrund Deines "findstr"-Ansatzes müsste ja das erste ";" bereits am Anfang stehen ...
Was soll denn in weiterer Folge mit den gefundenen Daten geschehen?
Und noch eine Frage: Da sich Batch nur bedingt zum Handling von einzelnen Zeichen eignet: Gibt es einen Einwand Deinerseits gegen die Verwendung von VBScript (vorzugsweise in einen Batch eingebettet)?
Grüße
bastla
Vielleicht holst Du etwas weiter aus und beschreibst eine solche Zeile näher (bzw postest ein Beispiel) - aufgrund Deines "findstr"-Ansatzes müsste ja das erste ";" bereits am Anfang stehen ...
Was soll denn in weiterer Folge mit den gefundenen Daten geschehen?
Und noch eine Frage: Da sich Batch nur bedingt zum Handling von einzelnen Zeichen eignet: Gibt es einen Einwand Deinerseits gegen die Verwendung von VBScript (vorzugsweise in einen Batch eingebettet)?
Grüße
bastla
Mal so ins Blaue mit den Infos bis jetzt könnte sowas gehen:
Sonderzeichen machen da aber Probleme
@echo off
FOR /F "tokens=1* delims=:" %%i in ('findstr /n /R ".*" "Datei.txt"') do call:search "%%j" %%i
goto:eof
:search
if "%~1" equ "" (
echo 0
goto:eof
)
set "line=%~1"
set /a i=0
set /a anzahl=0
:loop
set "z="
call set z=%%line:~%i%,1%%
if "%z%" equ "" (
echo %anzahl%
goto:eof
)
if "%z%" equ ";" set /a anzahl=%anzahl%+1
set /a i=%i%+1
goto:loop
@miniversum
Ins Blaue kann ich auch:
Ausgegeben werden alle Zeilen, in denen mehr als 3 ";" enthalten sind.
Grüße
bastla
Ins Blaue kann ich auch:
@echo off & setlocal
set "Datei=D:\Datei.txt"
set "Suche=;"
set /a Anz=3
set G=%temp%\GNO.vbs
>%G% echo Set rE=New RegExp:rE.Pattern="%Suche%":rE.Global=True:WScript.Echo rE.Execute(WScript.Arguments(0)).Count
for /f "tokens=1* delims=:" %%i in ('findstr /n "%Suche%" "%Datei%"') do (
for /f %%a in ('cscript //nologo %G% "%%j"') do (
if %%a gtr %Anz% echo %%j
)
)
Grüße
bastla
Hallo marlasdad!
Kurz zu "delims": Damit werden in einer "for /f"-Schleife das/die Trennzeichen festgelegt. Anhand dieser Trennzeichen erfolgt die Aufteilung der jeweils zu bearbeitenden Zeile - vergleichbar mit der "Split"-Funktion in VB. Das Ergebnis steht dann in alphabetisch benannten Variablen (frei wählbar, meist wird mit %%i begonnen) zur Verfügung. Wird "delims" nicht angegegen, gelten Leerzeichen und TAB als Trennzeichen. Es können auch mehrere Trennzeichen festgelegt werden (etwa "delims=.:", um einen Timestamp aufzusplitten). Ein explizites "delims=" (also ohne Angabe eines Trennzeichens) sorgt dafür, dass die Zeile ungetrennt in der Variablen zur Verfügung steht.
Mit der Angabe von "tokens" steuerst Du, welche Bestandteile der Zeile verwendet werden sollen - Beispiel:
würde aus einer CSV-Datei (tatsächlich mit Komma getrennt
) die Felder 1 bis 3 und 6, durch "-" verbunden, ausgeben. Eine oft nützliche weitere Schreibweise für "tokens" ist
Hier würden die Felder 1, 3, 5 sowie alle Felder ab 6 (letztere inklusive der Trennzeichen dazwischen) ausgegeben.
Um Deine Zeilen (Datensätze) aufzuteilen, müsstest Du also etwa so vorgehen (Beginn mit %%a, damit alle 21 Felder "Platz" haben):
Noch ein Hinweis: Die Schreibweise aller Beispiele mit 2 Prozentzeichen ist für die Verwendung in einem Batch gedacht - wenn Du an der Kommandozeile testen willst, jeweils nur ein Prozentzeichen verwenden.
Grüße
bastla
Allerding wäre natürlich VBS auch ok. DDas könnte ich ja dann aufrufen.
Ein (zusätzliches) VBScript ist gar nicht nötig - der Batch erstellt für die benötigte Funktionalität das Script selbst (siehe mein Ansatz oben).Kurz zu "delims": Damit werden in einer "for /f"-Schleife das/die Trennzeichen festgelegt. Anhand dieser Trennzeichen erfolgt die Aufteilung der jeweils zu bearbeitenden Zeile - vergleichbar mit der "Split"-Funktion in VB. Das Ergebnis steht dann in alphabetisch benannten Variablen (frei wählbar, meist wird mit %%i begonnen) zur Verfügung. Wird "delims" nicht angegegen, gelten Leerzeichen und TAB als Trennzeichen. Es können auch mehrere Trennzeichen festgelegt werden (etwa "delims=.:", um einen Timestamp aufzusplitten). Ein explizites "delims=" (also ohne Angabe eines Trennzeichens) sorgt dafür, dass die Zeile ungetrennt in der Variablen zur Verfügung steht.
Mit der Angabe von "tokens" steuerst Du, welche Bestandteile der Zeile verwendet werden sollen - Beispiel:
for /f "tokens=1-3,6 delims=," %%i in (D:\EineTextdatei.txt) do echo %%i-%%j-%%k-%%l
for /f "tokens=1,3,5* delims=," %%i in (D:\EineTextdatei.txt) do echo %%i-%%j-%%k-%%l
Um Deine Zeilen (Datensätze) aufzuteilen, müsstest Du also etwa so vorgehen (Beginn mit %%a, damit alle 21 Felder "Platz" haben):
for /f "tokens=1-21 delims=;" %%a in (D:\DeineDatei.txt) do echo %%a_%%b_..._%%u
Grüße
bastla
Hallo marlasdad!
Durch den Batch wird der Suchbegriff %Suche% (in diesem Fall ";") unmittelbar in den Scriptcode geschrieben. Das Script wird für jede Zeile der Textdatei (diese wird als Parameter übergeben) aufgerufen (was natürlich für eine große Zahl an Datensätezn entsprechend dauert) und liefert die Anzahl der enthaltenen Trennzeichen als Ausgabe an den Batch zurück.
Eine "VBS-only"-Variante sollte natürlich schneller sein:
Zu starten wäre das Script mit Übergabe der zu untersuchenden Datei, also etwa:
In dieser Fassung des Scripts erfolgt keine Prüfung auf Vorhandensein der Eingabedatei (kann aber schon im aufrufenden Batch erledigt werden). Die fehlerhaften Dateien werden (inkl max 8-stelliger Zeilennummern, rechtsbündig formatiert) in eine Datei im gleichen Pfad wie die übergebene Datei mit dem Namenszusatz "-Fehler" geschrieben.
Grüße
bastla
Und was macht das gno.vbs?
Das in Zeile 7 durch den Batch erzeugte Script sieht (etwas aufgeteilt) so aus:Set rE=New RegExp
rE.Pattern="%Suche%"
rE.Global=True
WScript.Echo rE.Execute(WScript.Arguments(0)).Count
Eine "VBS-only"-Variante sollte natürlich schneller sein:
Set rE = New RegExp
rE.Pattern = ";" 'Suchbegriff
rE.Global = True
Anzahl = 20 'Anzahl der Suchbegriffe, die nicht überschritten werden soll
Set fso = CreateObject("Scripting.FileSystemObject")
DateiEin = WScript.Arguments(0)
DateiAus = fso.GetParentFolderName(DateiEin) & "\" & _
fso.GetBaseName(DateiEin) & "-Fehler" & "." & _
fso.GetExtensionName(DateiEin)
Set Ein = fso.OpenTextFile(DateiEin)
Set Aus = fso.CreateTextFile(DateiAus, True)
i = 1
Do While Not Ein.AtEndOfStream
Zeile = Ein.ReadLine
If rE.Execute(Zeile).Count > Anzahl Then
Aus.WriteLine Right(Space(8) & i, 8) & ": " & Zeile
End If
i = i + 1
Loop
Aus.Close
Ein.Close
cscript //nologo CheckData.vbs "D:\Datei.txt"
Grüße
bastla