Batch Find and replace

Mosley

Newbie
Dabei seit
März 2015
Beiträge
2
Hallo liebe Community,

ich habe täglich die Aufgabe eine 10-20 tausend Zeilen große Textdatei zu bearbeiten.
Hierbei geht es darum einen Datumswert in einem String durch den aktuellen Datumswert zu ersetzen.

So sieht der Originalstring aus:

DTM+2:20150326:102'

Da das Datum welches in diesem String hinterlegt ist, selbst innerhalb der Datei ständig anders sein kann muss ich hier auf
regular exxpressions zurückgreifen.

Mit: \bDTM\+2:[0-9].......:102' bzw. \bDTM\+2:\d{8}:102'

gelingt es mir bereits alle Zeilen die DTM+2 am Zeilenanfang beinhalten zu erreichen und somit dann auch auszutauschen.


Der aktuelle Stand meines Skripts ist folgender:

@ECHO off
SETLOCAL enabledelayedexpansion

REM testprogramm zum Aendern von DTM 2 Inhalt

SET quelle=c:\dtm.txt
SET ziel=c:\hallowelt.txt

IF EXIST %ziel% DEL /f %ziel%

FOR /f "delims=" %%i IN ('FINDSTR /R . %quelle%') DO (
SET ganze_zeile=%%i
SET ganze_zeile=!ganze_zeile:\bDTM\+2:[0-9].......:102'=HalloWelt!
ECHO !ganze_zeile!
ECHO !ganze_zeile! >> %ziel%
)

pause


das ganze funktioniert auch sobald ich nicht "/R" als Parameter von FINDSTR angebe und einfach 1 zu 1 beispielsweise DTM durch HALLOWELT ersetze.

Sobald aber der reguläre Ausdruck greifen soll läuft die batch zwar, aber tut überhaupt nichts.

Ich bin mittlerweile ziemlich stark an der Grenze der Verzweiflung angekommen :-(

Vielleicht hat hier jemand eine Idee und könnte mir bei der weiteren Umsetzung helfen. Ich wäre euch sehr dankbar.
 
Zuletzt bearbeitet:

fhtagn

Ensign
Dabei seit
Nov. 2009
Beiträge
153
Kann es sein, dass SET keine regulären Ersetzungen erlaubt? Sieht mir fast danach aus.

Nächstes Problem: FINDSTR /R . %quelle% findet alle nicht leeren Zeilen. UN/Edifact-Nachrichten haben aber häufig nur eine Zeile, da ohne Umbrüche. Also lädt dir der erste Schleifendurchlauf die gesamte Datei ein.

Statt auf "." könntest du auf "[^']*'" matchen. Das findet alle Segmente. Dann muss jedes Segment nochmal auf DTM\+2[^']' geprüft werden. Wenn es nicht matcht, rausschreiben. Wenn es matcht, den Match durch dein aktuelles Datum ersetzen und das rausschreiben.

Ansonsten schließe ich mich BigNum an. Installier' dir vielleicht cygwin. Damit bekommst du eine von dir zusammengestellte Linux-Shell unter Windows. Mit perl/awk/sed ist dein Problem dann ein Einzeiler. Mit sed sähe die Lösung so aus:

Code:
sed -i "s/DTM+2[^']*'/Hallo Welt/g" message.edi
Ersetzt 'in place' alle DTM+2-Segmente durch 'Hallo Welt'. In eine andere Datei umleiten geht natürlich auch.
 

Mosley

Newbie
Ersteller dieses Themas
Dabei seit
März 2015
Beiträge
2
Vielen Dank für Eure Antworten.

Ich habe mich das Wochenende über ein bisschen mit dem Thema Cygwin auseinandergesetzt, komme damit allerdings bisher noch gar nicht klar :-(

Ich muss mir ein Skript zusammenbasteln, das einzelne EDIFACT-Dateien aus einem gewissen Ordner (am besten nach Timestamp) zusammenfügt und diese dann nach Möglichkeit in einen Ordner, der dem Timestamp der Dateien entspricht ablegt. Dort soll dann der bereits erwähnte Austausch der einzelnen DTM-Segmente erfolgen.

Die Daten sind in meinem Fall "nie" Einzeiler. Denn Sie laufen vorher durch einenn Konverter.
 

Yuuri

Fleet Admiral
Dabei seit
Okt. 2010
Beiträge
12.485
Benutz einfach die PowerShell. Ist vorinstalliert und kann mit Allem mithalten (.NET ist immer griffbereit).

Falls du matchen willst:
Code:
PS > "DTM+2:20150326:102" -match "^(?<before>.*?):(?<year>\d{4})(?<month>\d{2})(?<day>\d{2}):(?<after>.*)$"
True
PS > $matches

Name                           Value
----                           -----
year                           2015
day                            26
after                          102
month                          03
before                         DTM+2
0                              DTM+2:20150326:102
Falls du direkt ersetzen willst:
Code:
PS > "DTM+2:20150326:102" -replace "^(?<before>.*?):(?<year>\d{4})(?<month>\d{2})(?<day>\d{2}):(?<after>.*)$","`$1:$(Get-Date -Format "yyyyMMdd"):`$5"
DTM+2:20150330:102
 
Top