ole-objekt
Goto Top

Batch oder Powershell: Teile einer Textdatei kopieren (mehrere Zeilen)

Hallo,

ich habe mehrere txt-Dateien, in denen jeweils mehrere Abschnitte mit Daten vorliegen. Nun möchte ich jede dieser Textdateien "aufteilen", d.h. Abschnitte einer Art sollen in eine Datei kopiert werden, Abschnitte einer anderen Art in eine andere Datei. Konkret sieht das so aus:

Dateianfang
Abschnitt_Art_1
mehrere Zeilen
Abschnitt_Art_1
mehrere Zeilen
Abschnitt_Art_2
mehrere Zeilen
Abschnitt_Art_1
mehrere Zeilen
Abschnitt_Art_2
mehrere Zeilen
usw.
Dateiende

Abschnitt_Art_1 beginnt immer mit einer Zeile mit den ersten beiden Zeichen "#A" gefolgt von einem Leerzeichen
Abschnitt_Art_2 beginnt immer mit einer Zeile mit den ersten beiden Zeichen "#B" gefolgt von einem Leerzeichen

Innerhalb der Abschnitte gibt es keine Zeilen, die mit dieser Zeichenfolge beginnen.
Innerhalb der Abschnitte ist die Zahl der Zeilen variabel.
Es gibt bis zu 20.000 Abschnitte in einer Datei, die Reihenfolge der Abschnitte ist nicht festgelegt.

Nun soll jede Zeile geprüft werden, ob sie ein Abschnittsbeginn ist und wenn ja von welcher Art. Dann sollen diese erste Zeile und alle Folgezeilen bis zum nächsten Abschnittsbeginn in die passende Zieldateien kopiert werden, alle Abschnitte der Art_1 in die gemeinsame Zieldatei 1, alle der Art_2 in die gemeinsame Zieldatei 2.

Ich dachte, ich käme hiermit weiter, aber wenn ich die batch ausführe passiert nichts.

for %%f in (./*.txt) do (
     for /f tokens=1 %%i in (%%f) do (
          if %%i="#A" set ziel=A.txt  
          if %%i="#B" set ziel=B.txt  
          echo %%i>>ziel
     )
)

Was mache ich falsch?

Gruß, Olaf

Content-Key: 276861

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

Printed on: April 19, 2024 at 01:04 o'clock

Member: SeriousEE
SeriousEE Jul 09, 2015 at 12:49:07 (UTC)
Goto Top
Hallo,
Ist noch nicht perfekt, aber vielleicht hilft dir diese PS Script
$files = Get-ChildItem *.txt
$dest = "unknown.txt"  
foreach ($file in $files) {
  $text = Get-Content $file
  foreach ($line in $text) {
    if ($line.StartsWith("#")) {	   
	  $dest = $line[1]+".txt"  
	}
	else {
	  $line | out-File -append $dest
	}
  }
}


Viele Grüße
Mitglied: 114757
114757 Jul 09, 2015 updated at 18:14:14 (UTC)
Goto Top
Powershell gefällig face-wink
gci '.\*.txt' | %{  
    $dir = $_.DirectoryName
    [regex]::Matches((gc $_.Fullname | out-string),'(?sim)^#(A|B) [^\n\r]*(.*?)(?=^#|\Z)').Captures | group {$_.Groups[1]} | %{$_.Group.Value | out-file "$dir\$($_.Group.Groups[1].Value).txt" -Append}  
}
Gruß jodel32
Member: mikimoto
Solution mikimoto Jul 09, 2015, updated at Jul 16, 2015 at 18:34:58 (UTC)
Goto Top
Hallo, Olaf,

also bei mir hat das so funktioniert:

for %%f in (./*.txt) do (
   for /f "tokens=*" %%g in (%%f) do (  
		for /f "tokens=1" %%i in ("%%g") do (  
			if %%i == #A echo %%g >> A.txt
			if %%i == #B echo %%g >> B.txt
		)
	)
)

Achte besonders auf die Anführungszeichen in Zeile 3: "%%g".

Gruß, Michael

Oh, ich hab ganz übersehen, dass du ja noch eine weitere Bedingung hattest: Innerhalb der Abschnitte beginnt keine der Zeilen mit #A oder #B.
Da muss ich wohl noch etwas nacharbeiten.
Member: mikimoto
Solution mikimoto Jul 09, 2015, updated at Jul 16, 2015 at 18:34:46 (UTC)
Goto Top
Hallo, Olaf,

jetzt nochmal meine aktualisierte Fassung.
Ich hoffe, ich habe jetzt alles richtig verstanden.

Du hast eine (oder mehrere) .txt-Dateien mit etwa folgendem Inhalt:

#A zeile 1
#B Zeile 2
Zeile 3
Zeile 4
#A Zeile 5
#B Zeile 6
#A Zeile 7
Zeile 8

Meine Batch-Datei sieht folgendermaßen aus:

@echo off
setlocal enabledelayedexpansion
for %%f in (.\*.txt) do (
   for /f "tokens=*" %%g in (%%f) do (  
		for /f "tokens=1" %%i in ("%%g") do (  
			if %%i == #A set ziel=A.txt
			if %%i == #B set ziel=B.txt
			echo %%g >> !ziel!
		)
	)
)

Das Ergebnis sind zwei Dateien, einmal
A.txt:
#A zeile 1 
#A Zeile 5 
#A Zeile 7 
Zeile 8

und dann
B.txt
#B Zeile 2 
Zeile 3 
Zeile 4 
#B Zeile 6

Das müsste es doch sein, oder?

Das Problem sind die Umgebungsvariablen innerhalb von IF-Strukturen. Achte daher auf die Ausrufezeichen in Zeile 8.

Siehe hierzu auch hier.

Gruß, Michael
Member: format-c
Solution format-c Jul 10, 2015, updated at Jul 16, 2015 at 18:34:28 (UTC)
Goto Top
Hallo Olaf.
Ich weiß nicht wie es in Powershell ist, aber was den Befehlszeileninterpreter CMD angeht, fallen mir ein paar Punkte ein:
1. If-Vergleiche von Zeichenketten werden mit doppelten Gleichheitszeichen (==) gemacht.
2. Anführungszeichen zählen zum String dazu, d.h. sie müssen entweder auf beiden Seiten vorhanden sein oder auf beiden Seiten fehlen, sonst gibt es keine Gleichheit. ("A"=="A" und nicht A=="A")
3. Wenn du innerhalb einer For-Schleife eine Variable aufrufst, die du in derselben For-Schleife (ein paar Zeilen zuvor) geändert hast (in deinem Beispiel %ziel%), benötigst du die Direktive
SETLOCAL EnableDelayedExpansion
und die Variable muss dann statt %% in !! eingeschlossen werden (s. Beispiele meiner Vorredner).
4. tokens=1 muss in Anführungszeichen eingeschlossen werden. (siehe for /?)

Gruß
format-c