Top-Themen

AppleEntwicklungHardwareInternetLinuxMicrosoftMultimediaNetzwerkeOff TopicSicherheitSonstige SystemeVirtualisierungWeiterbildungZusammenarbeit

Aktuelle Themen

Administrator.de FeedbackApache ServerAppleAssemblerAudioAusbildungAuslandBackupBasicBatch & ShellBenchmarksBibliotheken & ToolkitsBlogsCloud-DiensteClusterCMSCPU, RAM, MainboardsCSSC und C++DatenbankenDatenschutzDebianDigitiales FernsehenDNSDrucker und ScannerDSL, VDSLE-BooksE-BusinessE-MailEntwicklungErkennung und -AbwehrExchange ServerFestplatten, SSD, RaidFirewallFlatratesGoogle AndroidGrafikGrafikkarten & MonitoreGroupwareHardwareHosting & HousingHTMLHumor (lol)Hyper-VIconsIDE & EditorenInformationsdiensteInstallationInstant MessagingInternetInternet DomäneniOSISDN & AnaloganschlüsseiTunesJavaJavaScriptKiXtartKVMLAN, WAN, WirelessLinuxLinux DesktopLinux NetzwerkLinux ToolsLinux UserverwaltungLizenzierungMac OS XMicrosoftMicrosoft OfficeMikroTik RouterOSMonitoringMultimediaMultimedia & ZubehörNetzwerkeNetzwerkgrundlagenNetzwerkmanagementNetzwerkprotokolleNotebook & ZubehörNovell NetwareOff TopicOpenOffice, LibreOfficeOutlook & MailPapierkorbPascal und DelphiPeripheriegerätePerlPHPPythonRechtliche FragenRedHat, CentOS, FedoraRouter & RoutingSambaSAN, NAS, DASSchriftartenSchulung & TrainingSEOServerServer-HardwareSicherheitSicherheits-ToolsSicherheitsgrundlagenSolarisSonstige SystemeSoziale NetzwerkeSpeicherkartenStudentenjobs & PraktikumSuche ProjektpartnerSuseSwitche und HubsTipps & TricksTK-Netze & GeräteUbuntuUMTS, EDGE & GPRSUtilitiesVB for ApplicationsVerschlüsselung & ZertifikateVideo & StreamingViren und TrojanerVirtualisierungVisual StudioVmwareVoice over IPWebbrowserWebentwicklungWeiterbildungWindows 7Windows 8Windows 10Windows InstallationWindows MobileWindows NetzwerkWindows ServerWindows SystemdateienWindows ToolsWindows UpdateWindows UserverwaltungWindows VistaWindows XPXenserverXMLZusammenarbeit
GELÖST

Skript für Template-Filegenerierung

Frage Entwicklung Batch & Shell

Mitglied: filippg

filippg (Level 3) - Jetzt verbinden

01.09.2010 um 20:51 Uhr, 3747 Aufrufe, 6 Kommentare

Suche Programm, dass aus einem Template und einer .csv für jede Zeile ein ausgefülltes Template erzeugt

Hallo,

ich suche etwas, das bestimmt irgendwer schon irgendwo im Internet gepostet hat, aber ich finde es nicht:
Ich habe ein Programm, das z.B. Nutzeranlagen als einzelne XML-Files entgegennimmt. Wenn ich nun eine Liste mit 20 Nutzeranlagen habe, muss ich 20 XML-Files erstellen, in denen ich jeweils nur den Name veränder. Das ist irgendwie umständlich, und muss doch auch einfacher gehen.
Ich suche also ein Skript mit folgender Funktionalität:
Übergeben werden zwei Dateien: Eine .csv mit beliebiger Spalten- und Zeilenzahl und ein Template. In dem Template sind Platzhalter entsprechend den Spaltennamen enthalten. Für jede Zeile erzeugt das Skript nun eine neue Datei, in der die Platzhalter mit den entsprechenden Spaltenwerten ersetzt werden.

Kann mir jemand bei der Suche weiterhelfen?

Danke

Filipp
Mitglied: bastla
01.09.2010 um 21:53 Uhr
Hallo filippg!

Wozu suchen - selber schreiben ...

... als VBS schematisch (und ungetestet) etwa so:
01.
CSV = "D:\Die.csv" 
02.
Delim = ";" 
03.
Template = "D:\Template.xml" 
04.
Pfad = "D:\Ausgabepfad XML-Dateien" 
05.
 
06.
Set fso = CreateObject("Scripting.FileSystemObject") 
07.
TemplateText = fso.OpenTextFile(Template).ReadAll 'Templateinhalt einlesen 
08.
Daten = Split(fso.OpenTextFile(CSV).ReadAll, vbCrLf) 'Daten aus CSV in Array einlesen 
09.
Felder = Split(Daten(0), Delim) 'Feldnamen = Platzhalter aus erster Zeile der CSV in  Array einlesen 
10.
 
11.
For i = 1 To UBound(Daten) 'alle Datensätze durchgehen 
12.
    Info = Split(Daten(i), Delim) 'Informationen aus den einzelnen Feldern des Datensatzes in Array einlesen 
13.
    XML = Pfad & "\" & Info(0) & ".xml" 'Dateiname aus erstem Feld übernehmen 
14.
    XMLText = TemplateText 'Originaltemplate als Ausgangspunkt 
15.
    For j = 0 To UBound(Info) 'alle Felder durchgehen 
16.
        XMLText = Replace(XMLText, Felder(j), Info(j)) 'anhand der Feldnamen die Platzhalter durch die eingelesenen Informationen erstezen 
17.
    Next 
18.
    fso.CreateTextFile(XML).Write XMLText 'Datei schreiben 
19.
Next
Vorausgesetzt wird, dass die Platzhalter als Feldnamen in der der ersten Zeile der CSV-Datei in der exakt gleichen Schreibweise stehen und es keine Fehler in der Struktur der Daten gibt.
Da ich keine Informationen über die Namen der Zieldateien hatte, wird einfach der Inhalt des jeweils ersten Feldes als Name verwendet ...

[Edit] Inzwischen oberflächlich getestet und einige Fehler korrigiert. [/Edit]

Grüße
bastla
Bitte warten ..
Mitglied: filippg
03.09.2010 um 19:28 Uhr
Hallo Bastla,

vielen Dank für dein Skript.
Es sind halt immer die Feinheiten, die das Skripten anstrengend machen - und ich hatte gehofft ein Skript zu finden, das diese Feinheiten schon enthält, so dass ich mich darum nicht selber kümmern muss. Z.B. wird das Skript nicht damit klarkommen, wenn das Delimiterzeichen in einem Feld enthalten ist. Hübsch wäre auch ein Skript, dass "vernünftig" reagiert, wenn die Ausgabedatei schon vorhanden ist, etc...
Aber scheinbar werde ich mir da wirklich gelegentlich mal ewtas selbst basteln müssen.... mal schauen, wann ich dazu komme, poste es dann hier.

Gruß

Filipp
Bitte warten ..
Mitglied: bastla
04.09.2010 um 22:06 Uhr
Hallo Filipp!

Mein Ansatz war ja nur als Grundgerüst gedacht - eine "vernünftige" Reaktion auf bereits vorhandene Ausgabedateien kann ja, wenn sie einmal definiert ist , nicht so schwer zu realisieren sein ...

Etwas kniffliger:
Z.B. wird das Skript nicht damit klarkommen, wenn das Delimiterzeichen in einem Feld enthalten ist.
Abgesehen davon, dass ja Du die CSV erstellst oder zumindest Einfluss darauf haben solltest und Dir wohl nicht selbst Knüppel zwischen die Beine werfen wirst, ließe sich auch das (vermutlich noch eleganter) lösen - zB als mit "cscript" zu startende Demo für eine Zeile:
01.
Zeile = """;Feld1"";Feld2;""Feld3;"";"""";""Feld 5"";""Feld 6 mit ; im Wert"";;;Feld 9" 
02.
Delim = ";" 
03.
 
04.
Auf = "{"   'beliebiges nicht in den Daten enthaltenes Zeichen 
05.
Zu = "}"    'anderes nicht in den Daten enthaltenes Zeichen 
06.
Dummy = "@" 'noch ein nicht in den Daten enthaltenes Zeichen 
07.
 
08.
WScript.Echo "Original   :" & Zeile 
09.
 
10.
'Unmittelbar aufeinander folgende Anführungszeichen kennzeichnen ein leeres Feld und ... 
11.
'... können daher vorweg durch "Nichts" ersetzt werden 
12.
Z = Replace(Zeile, """""", "") 
13.
WScript.Echo "Leer ohne "":" & Z 
14.
 
15.
Set rE = New RegExp 
16.
rE.Global = True 
17.
'Suche nach paarweisen Anführungszeichen ... 
18.
rE.Pattern = "("")([^""]*)("")" 
19.
'... und Ersetzen durch öffnende und schließende Klammern 
20.
Z = rE.Replace(Z, Auf & "$2" & Zu) 
21.
WScript.Echo "Geklammert :" & Z 
22.
 
23.
'Suche nach Vorkommen von Trennzeichen innerhalb der Klammern, zB {abc;xyz} und ... 
24.
 
25.
'Aufteilung:  (          $1         )     (   $2    )     (         $3        ) 
26.
rE.Pattern = "(" &Auf&"[^"&Delim&"]*)" & "("&Delim&")" & "([^"&Delim&"]*"&Zu&")" 
27.
'Ergebnis:             $1={abc               $2=;                 $3=xyz} 
28.
 
29.
'... Ersetzen des im Feld enthaltenen Trennzeichens = $2 durch einen "Dummy"-Wert ... 
30.
Z = rE.Replace(Z, "$1" & Dummy & "$3") 
31.
'... sowie Entfernung der umschließenden Klammern "{" und "}" 
32.
Z = Replace(Replace(Z, Auf, ""), Zu, "") 
33.
WScript.Echo "mit Dummy  :" & Z & vbCrLf 
34.
 
35.
'Zerlegung anhand des Trennzeichens in Felder 
36.
Felder = Split(Z, Delim) 
37.
For i = 0 To UBound(Felder) 'Durchlaufen der einzelnen Felder 
38.
    'Demo-Ausgabe mit Rückwandlung des "Dummy"-Wertes in das Trennzeichen 
39.
    WScript.Echo "Feld " & i + 1 & ": |" & Replace(Felder(i), Dummy, Delim) & "|" 
40.
Next
Vorausgesetzt habe ich, dass Felder, welche das Trennzeichen enthalten, auf jeden Fall unter Anführungszeichen stehen (ansonsten wäre ja eine Unterscheidung, noch dazu bei der gewünschten variablen Feldanzahl, gar nicht möglich). Zerlegt wird in dieser Demo die (mit ein paar "Spezialfällen" angereicherte) Zeile
";Feld1";Feld2;"Feld3;";"";"Feld 5";"Feld 6 mit ; im Wert";;;Feld 9
Grüße
bastla
Bitte warten ..
Mitglied: filippg
05.09.2010 um 03:35 Uhr
Hallo Bastla,

entschuldige, das waren beides nur als Beispiele gedacht. Das "Delimiter im Text"-Problem ergibt sich bei Powershell (die ich wohl nehmen werde) nicht, da die ein entsprechend sorgfältig implementiert ist. Und zur schon existierenden Ausgabedatei: klar, das lässt sich leicht abfangen. Aber das ist es eben: es sind zig Kleinigkeiten, an die man denken muss, wenn es wirklich gut sein soll. Und Kleinvieh macht auch Mist... Deswegen habe ich auch für ein solches eigentlich triviales Problem nach einer guten Fertiglösung gesucht...

Gruß

Filipp
Bitte warten ..
Mitglied: bastla
05.09.2010 um 11:18 Uhr
Hallo Filipp!
Deswegen habe ich auch für ein solches eigentlich triviales Problem nach einer guten Fertiglösung gesucht...
Dagegen habe ich ja auch gar nix einzuwenden - mir macht einfach nur das Scripten Spaß ...

Grüße
bastla
Bitte warten ..
Mitglied: filippg
26.10.2010 um 19:41 Uhr
Hallo,

ich hatte ganz vergessen hier zu posten, was ich jetzt verwende. Voilá:
01.
param( 
02.
[string]$Template, 
03.
[string]$csv 
04.
05.
$Description = " 
06.
Erwartet als ersten Parameter eine Template-Datei (beliebiges  
07.
Dateiformat), als zweiten eine .csv. Für jeden Datensatz in der 
08.
.csv wird das Template einmal ausgefüllt. Platzhalter, die in 
09.
## eingeschlossen sind werden durch den jeweiligen Spaltenwert 
10.
ersetzt. 
11.
Liegt im aktuellen Verzeichnis nur eine .csv-Datei, so muss 
12.
diese nicht mit angegeben werden. 
13.
Gibt es eine Spalte 'OutFile', so wird ihr Wert dem Ausgabe- 
14.
Dateiname angehängt. 
15.
(C) Filipp Geyer, 2010 
16.
17.
 
18.
if($Template -eq "") { 
19.
        Write-Host $Description 
20.
        break 
21.
22.
if($csv -eq ""){ 
23.
        $csvsInDir = Get-ChildItem "." -Filter "*.csv" 
24.
        if(($csvsInDir | Measure-Object).Count -eq 1) 
25.
                { $csv = $csvsInDir.FullName } 
26.
        else  
27.
                { Write-Host -ForegroundColor Red Es wurde keine Eingabedatei angegegeben, und es wurde keine oder mehr als eine .csv-Datei im Arbeitsverzeichnis gefunden; break} 
28.
29.
 
30.
if(-not(Test-Path -PathType Leaf $template)) 
31.
        {Write-Host -ForegroundColor Red Templatedatei $template konnte nicht gefunden werden; break } 
32.
$templateObj = Get-Item $Template 
33.
$templateBaseName = $templateObj.Name.Remove($templateObj.Name.Length - $templateObj.Extension.Length) 
34.
 
35.
if(-not(Test-Path -PathType Leaf $csv)) 
36.
        {Write-Host -ForegroundColor Red Eingabedatei $csv konnte nicht gefunden werden; break } 
37.
 
38.
$inFileObj = Get-Item $csv 
39.
if($inFileObj.Extension -ne ".csv") 
40.
        {Write-Host -ForegroundColor Red Eingabedatei $csv hat nicht die Endung .csv; break } 
41.
 
42.
function getNextFileName([string]$path, [string]$fileName, [string]$fileExt){ 
43.
        if(-not (Test-Path -PathType Container $path )){ 
44.
                Write-Host -ForegroundColor Red Ausgepfad $path existiert nicht! 
45.
                break 
46.
47.
        $currFileName = $path + "\" + $fileName  + $fileExt 
48.
         
49.
        for($i = 2; $i -lt 999; $i++){ 
50.
                if(-not (Test-Path -PathType Leaf $currFileName)){ 
51.
                        return $currFileName} 
52.
                $currFileName = $path + "\" + $fileName + "_" + $i + $fileExt    
53.
54.
        Write-Host -ForegroundColor Red Konnte keinen Dateinamen fuer die Ausgabe finden. 
55.
        break; 
56.
57.
 
58.
$dataset = Import-Csv $csv 
59.
$cols = $dataset | Get-Member -MemberType NoteProperty 
60.
$contTemplate = Get-Content $template 
61.
foreach($row in $dataset){ 
62.
        $currCont = $contTemplate 
63.
         
64.
        $outFile = getNextFileName $inFileObj.Directory.FullName ($templateBaseName + $row.OutFile) $templateObj.Extension 
65.
        foreach($col in $cols){  
66.
                $currCont = $currCont -replace ("##"+$col.Name+"##"), ($row.($col.Name)) 
67.
68.
         
69.
        $currCont > $outFile     
70.
}
Grüße

Filipp
Bitte warten ..
Neuester Wissensbeitrag
Windows 10

Powershell 5 BSOD

(8)

Tipp von agowa338 zum Thema Windows 10 ...

Ähnliche Inhalte
Windows Server
gelöst Skript per GPO ausführen - Berechtigungen? (13)

Frage von honeybee zum Thema Windows Server ...

Vmware
ESXI Template erstellen (2)

Frage von Phill93 zum Thema Vmware ...

Batch & Shell
Powershell CHAT Skript (5)

Frage von xpxy15 zum Thema Batch & Shell ...

Heiß diskutierte Inhalte
LAN, WAN, Wireless
gelöst Server erkennt Client nicht wenn er ausserhalb des DHCP Pools liegt (28)

Frage von Mar-west zum Thema LAN, WAN, Wireless ...

Outlook & Mail
gelöst Outlook 2010 findet ost datei nicht (19)

Frage von Floh21 zum Thema Outlook & Mail ...

Microsoft
Ordner mit LW-Buchstaben versehen und benennen (19)

Frage von Xaero1982 zum Thema Microsoft ...

Netzwerkmanagement
gelöst Anregungen, kleiner Betrieb, IT-Umgebung (18)

Frage von Unwichtig zum Thema Netzwerkmanagement ...