Dateien lesen, Zeichen extrahieren, an den Anfang aller Zeilen anhängen, Kopf- und Fußzeile streichen, alle Dateien verketten

1

Ich habe eine große Menge von ASCII-Textdateien, die ich mit dem in der Datei gefundenen Inhalt ändern und dann in einer Zusammenfassungsdatei zusammenfassen muss. Ich hatte bisher einen moderaten Erfolg mit einem schrittweisen Ansatz. Aber ich möchte das auf einen Schlag machen und konnte es nicht herausfinden. Ich habe in PowerShell ein Skript geschrieben, das für eine Datei das tut, was ich will, aber ich kann nicht herausfinden, wie ich sie für alle Dateien im Ordner ändern kann. Ich habe mit der Endlosschleife und den Endabschnitten der Verkettung von Dateien zu kämpfen.

Hier ist meine grundlegende Dateistruktur:

File1.txt

Line1 - abc123 - header (Ich möchte die Zeichen 2, 3 und 4 von hier entfernen und zu den Datenzeilen hinzufügen)
Zeile2 - Daten1
Line3 - data2
LineN - abc123 - footer (ein Duplikat der Kopfzeile)

File2.txt

Line1 - efg456
Zeile2 - Daten3
Zeile3 - Daten4
LineN - efg456

FileN.txt

Line1 - hij789
Zeile2 - Daten5
Zeile3 - Daten6
LineN - hij789

Ich möchte, dass die endgültige Ausgabedatei die folgende Struktur hat, wobei die Kopf- und Fußzeilen entfernt und der Inhalt aus der Kopfzeile in einer neuen Spalte am Anfang der Datei extrahiert wird (dies sind Dateien mit fester Breite):

Final.txt

Line1 - bc1data1
Line2 - bc1data2
Line3 - fg4data3
Zeile4 - fg4data4
Line5 - ij7data5
Line6 - ij7data6

Ich konnte dieses Problem für eine Datei lösen und habe den folgenden Code eingefügt:

cd "C:\Data\Files\"
$S1 = Get-Content File1.txt -First 1
$S2 = $S1.Substring(2,3)
Get-Content File1.txt | ForEach-Object {Add-Content a.txt "$S2$_"}
Get-Content a.txt | Select -Skip 1 | Select -SkipLast 1 | Set-Content out.txt
# extract header line
# limit to characters of interest
# append to the beginning of each line in file
# append all files together w/o first & last line

Im Idealfall könnte ich dies auch ohne die Junk-Datei a.txt tun, aber ich konnte es erst durch Schreiben in eine separate Datei zum Laufen bringen. Anregungen / Tipps sind willkommen, da ich in PowerShell noch relativ neu bin (einige Stunden Übung).

Karl
quelle

Antworten:

0
## Q:\Test\2017\08\25\SU_1244148.ps1

Set-Location "C:\Data\Files\"
$Files = Get-ChildItem File*.txt
$Final = ForEach ($File in $Files){
    $Content = Get-Content $File
    $Prefix = $Content[0].Substring(1,3)
    For ($i = 1;$i -lt $Content.Length-1;$i++){
         "{0}{1}" -f $Prefix,$Content[$i]
    } 
} 
$Final | Set-Content Final.txt

> gc .\Final.txt
bc1data1
bc1data2
fg4data3
fg4data4
ij7data5
ij7data6

Version 2 verarbeitet große Dateien

## Q:\Test\2017\08\25\SU_1244148_2.ps1
#Set-Location "C:\Data\Files\"

$Files = (Get-ChildItem File*.txt|Sort)
$Final = '.\Final.txt'

## As we append to $Final initially clear
If (Test-Path $Final){Remove-Item $Final}

ForEach ($File in $Files){
    $Reader = [IO.File]::OpenText($File)
    $Header = $Reader.ReadLine()
    $Prefix = $Header.SubString(1,3)
    $Line = $Reader.ReadLine()
    while ($Reader.Peek() -ge 0) {
        $Prefix+$Line| Out-File $Final -Append
        $Line = $Reader.ReadLine()
    }
    $Reader.Dispose()
} 

Optimierter Code, um nicht auf abschließenden Header testen zu müssen.
Die while-Schleife druckt die vorherige Zeile und liest die nächste Zeile, wobei die letzte Zeile gelöscht wird.

LotPings
quelle
Danke, @LotPings, es hat großartig mit kleinen Testdateien funktioniert, aber sobald ich es mit großen Dateien ausgeführt habe, hat es eine Ausnahme wegen zu wenig Arbeitsspeicher gegeben.
Karl
Im dieses Q & amp; A auf SO sind einige Konzepte, die sich mit großen Dateien beschäftigen. Siehe beigefügte 2. Skriptversion. Eine positive Bewertung wert ;-)
LotPings
Ich habe das jetzt für ein bisschen zurückgelegt. Version 2 funktionierte gut für mich, war jedoch sehr langsam, wenn ich große Dateien (& gt; = 0,5 GB) ausführte. Also habe ich die Out-File-Zeile gegen StreamWriter.WriteLine () ausgetauscht.
Karl