django.durano
Goto Top

Bestimmten Bereich einer Textdatei ausgeben mittels Batch

Hallo,

gibt es eine Möglichkeit eine Textdatei mittels Batch zu durchsuchen und einen bestimmten Teil davon dann aber nur auszugeben?

Folgendes Beispiel:

Meine Textdatei sieht wie folgt aus:

Episode
1
2
3
4
5
6

Beschreibung
Hier steht eine Beschreibung

usw.

Besteht hier nun die Möglichkeit nach Episode zu suchen und dann alles was nach Episode folgt bis Beschreibung auszugeben und bei Beschreibung zu stoppen?
Das was zwischen Episode steht also 1,2,3 usw. variert, ist also nicht immer eine bestimmte Anzahl.

Ich kenne mich etwas mit Batchrex aus und wie ich eine normale Textdatei durchsuche und dann eben das auszugeben was dort drin steht, allerdings weis ich nicht ob es möglich ist nur einen bestimmten Bereich zu durchsuchen.

Ich denke hier muss man mit Regular Expressions arbeiten, damit kenne ich mich aber leider nicht wirklich aus.

Hoffe konnte vermittlen was ich gerne hätte.

Gruß Django

Content-ID: 347848

Url: https://administrator.de/contentid/347848

Ausgedruckt am: 23.11.2024 um 17:11 Uhr

rubberman
Lösung rubberman 31.08.2017 um 20:34:01 Uhr
Goto Top
Der Regex Support von Batch beschränkt sich auf das bisschen, was FINDSTR versteht (wenn man nicht auf andere Sprachen oder Drittprogramme zurückgreifen will).

Gehen wir von folgenden Voraussetzungen aus:
- Die Textdatei ist in einer Single Byte Codepage codiert.
- Die Suchbegriffe bilden eine separate Zeile (ohne voran- oder nachgestellte Leer- oder sonstige Zeichen).
- Die maximale Länge einer Zeile überschreitet nicht 1021 Zeichen.

@echo off &setlocal
set "infile=test.txt"  

for /f "delims=:" %%i in ('findstr /nx "Episode" "%infile%"') do set "begin=%%i"  
for /f "delims=:" %%i in ('findstr /nx "Beschreibung" "%infile%"') do set /a "end= %%i - begin - 1"  

setlocal EnableDelayedExpansion
<"!infile!" (  
  for /l %%i in (1 1 %begin%) do set /p "="  
  for /l %%i in (1 1 %end%) do (
    set "line=" &set /p "line="  
    echo(!line!
  )
)
pause

Grüße
rubberman
Django.Durano
Django.Durano 02.09.2017 um 17:17:28 Uhr
Goto Top
Danke für deine schnelle Antwort.
Der Code erfüllt genau was ich mir vorgestellt habe.

Nur kurz zum Verständnis.

for /f "delims=:" %%i in ('findstr /nx "Episode" "%infile%"') do set "begin=%%i"  
for /f "delims=:" %%i in ('findstr /nx "Beschreibung" "%infile%"') do set /a "end= %%i - begin - 1"  

Die beiden For-Schleifen sind quasi dafür gedacht um den Bereich abzustecken zwischen Epsiode und Beschreibung sehe ich das richtig?
Der Command /nx steht hier gleichnamig für /n /x oder?

setlocal EnableDelayedExpansion
<"!infile!" (  
  for /l %%i in (1 1 %begin%) do set /p "="  
  for /l %%i in (1 1 %end%) do (
    set "line=" &set /p "line="  
    echo(!line!
  )
)

In dem Block hier wird quasi anhand des oben abgesteckten Bereiches Zeilenweise durchgezählt und das gefundene dann ausgegeben?`

Soweit richtig?


Gruß Django
rubberman
rubberman 02.09.2017 um 18:07:56 Uhr
Goto Top
Ja, /nx ist hier kurz für /n /x. Das /n führt dazu, dass FINDSTR der gefundenen Zeile die Zeilennummer und ein Doppelpunkt voranstellt (und die Zeilennummer ist das, was wir jeweils brauchen). Das /x bedeutet, dass die gesamte Zeile dem Suchpattern entsprechen muss. Anderenfalls würden auch Zeilen gefunden, die das Suchpattern nur an irgendeiner Stelle beinhalten.

Das <"!infile!" (leitet den Filestream an den kompletten Klammernblock um, sodass mit SET /P jeweils eine Zeile gelesen wird.
Die erste FOR /L Schleife liest also alle Zeilen bis zum Beginn des gesuchten Blocks. Der Zeileninhalt wird aber keiner Variablen zugewiesen (also wird er de facto verworfen).
Die zweite FOR /L Schleife liest die vorher mit SET /A berechnete Anzahl an Zeilen jeweils in Variable lineein und gibt sie mit ECHO aus.

Grüße
rubberman
77559
77559 03.09.2017 um 13:57:30 Uhr
Goto Top
Unter den gleichen Prämissen wie bei rubberman ist diese Batchdatei etwas simpler:

@echo off &setlocal
set "InFile=test.txt"  
set "Von=Episode"  
set "Bis=Beschreibung"  
set "Flag="  
For /f "tokens=1* delims=]" %%A in ('find /V /N "§+#*$" ^<%InFile%') DO (  
    if "%%B"=="%Bis%"  Set "Flag="  
    If defined Flag echo:%%B
    if "%%B"=="%Von%" Set "Flag=1"  
)

Mit PowerShell tut's ein (wenn auch komplexer) Einzeiler, nutzbar von der cmdline oder auch in einer Batchdatei:
powershell -NoP -C "gc test.txt -raw |sls '(?sm)(?<=^Episode\r?\n).*(?=\r?\nBeschreibung)'|%{$_.Matches.value}"  

Dasselbe als PowerShell Script ohne Aliase:
Get-Content test.txt -Raw | 
  Select-String '(?sm)(?<=^Episode\r?\n).*(?=\r?\nBeschreibung)'|  
    ForEach-Object {
      $_.Matches.value
    }

Kern ist ein Regulärer Ausdruck (RegEX) mit Lookarounds

Gruß LotPings
rubberman
rubberman 03.09.2017 um 19:58:24 Uhr
Goto Top
Zitat von @77559:
... ('find /V /N "§+#*$" ^<%InFile%') ...

Nanu face-surprise ... ('find /V /N "" ^<"%InFile%"') ... oder haben die Zeichen irgendeine Bewandtnis, die ich nicht verstehe?

Grüße
rubberman
Django.Durano
Django.Durano 05.09.2017 aktualisiert um 11:18:08 Uhr
Goto Top
@77559
Erstmal danke für deine Antwort.


@echo off &setlocal
set "InFile=test.txt"  
set "Von=Episode"  
set "Bis=Beschreibung"  
set "Flag="  
For /f "tokens=1* delims=]" %%A in ('find /V /N "§+#*$" ^<%InFile%') DO (  
    if "%%B"=="%Bis%"  Set "Flag="  
    If defined Flag echo:%%B
    if "%%B"=="%Von%" Set "Flag=1"  
)

Ehrlich gesagt verstehe ich deine Batch viel weniger als die von Rubberman. Außerdem fehlt hier nicht auch die Definition von %%B?
%%A wird ja durch die For-Schleife deklariert aber %%B fehlt mir irgendwie.
Würde ja dann heißen wenn
leer==Beschreibung set flag=
Oder habe ich etwas übersehen?


@rubberman

Danke für die Erklärung. Das umleiten des Filestreams ist mir aber noch nicht ganz klar bzw. wie ich das genau anwenden kann.
Ich kannte bisher nur das ich den Filestream in eine Textdatei umleiten kann mit > bzw. >>
Ist das hier quasi so eine Art Umkehrung, das die Textdatei eingelesen und hierdurch dann übergeben wird an das nachfolgende?
rubberman
rubberman 05.09.2017 um 12:10:06 Uhr
Goto Top
Zitat von @Django.Durano:
Ich kannte bisher nur das ich den Filestream in eine Textdatei umleiten kann mit > bzw. >>
Ist das hier quasi so eine Art Umkehrung, das die Textdatei eingelesen und hierdurch dann übergeben wird an das nachfolgende?
Fast. >und >>leiten das stdout an einen Filestream um, während <einen Filestream an das stdin umleitet. Insgesamt gibt es 3 Standarddatenströme. Der 3. ist das stderr. Hast vielleich schon gemerkt, dass du 2>oder 2>>schreiben musst, um Fehlermeldungen umzuleiten.

Grüße
rubberman
77559
77559 05.09.2017 um 21:50:59 Uhr
Goto Top
@rubberman
  • Der String "§+#*$" in Verbindung mit /V als unwahrscheinlich vorkommender Teil (soll alles durchlassen, es geht um die Numerierung)
> find /V /N "$$$" <test.txt  
[1]Episode
[2]1
[3]2
[4]3
[5]4
[6]5
[7]6
[8]
[9]Beschreibung
[10]Hier steht eine Beschreibung
[11]
[12]usw.
@django
  • Ich finde eine Schleife einfacher als vier - aber ein paar Erklärungen mehr hätten nicht geschadet.
  • find statt findstr wegen der eckigen Klammer als Abgrenzung ( die schließende Klammer dürfte seltener als erstes Zeichen einer Zeile auftreten als ein Doppelpunkt)
  • Die Umleitung damit find nicht den Dateinamen mit ausgibt.
  • Das Flag statt eines Variableninhalts der EnableDelayedExpansion erfordern würde (if defined funktioniert auch ohne)
  • Flag funktioniert als Schalter wann ausgegeben werde soll
  • mit tokens wird festgelegt wieviele Variablen genutzt werden 1=%%A, *=%%B (Rest der Zeile) %%A enthält nur die verworfene Numerierung in eckigen Klammern [1] etc.
rubberman
rubberman 05.09.2017 um 23:39:40 Uhr
Goto Top
Zitat von @77559:

@rubberman
  • Der String "§+#*$" in Verbindung mit /V als unwahrscheinlich vorkommender Teil (soll alles durchlassen, es geht um die Numerierung)
Joa und der leere String "" in Verbindung mit /V findet alle Zeilen die nicht nichts enthalten und auch nicht keinen Zeilenumbruch haben, also alle Zeilen incl. Leerzeilen face-wink
Ansonsten war mir klar, wie es funktioniert. (Die Erklärung wird aber für Django.Durano sicher nützlich sein.)

Grüße
rubberman
Django.Durano
Django.Durano 09.09.2017 um 14:40:47 Uhr
Goto Top
Erstmal danke für eure Hilfe.

Ich schau mir den Code von Lotpings nochmal an.
Wenn ich noch Fragen habe melde ich mich einfach wieder.