[Powershell] Eine Zeile mit bestimmten Tags auslesen und diese af mehrere Zeilen vert

rkrause

Mitglied
Da ich eigentlich mehr oder weniger professionel mit Powershell gearbeitet habe, wurde ich gefragt, ob ich folgendes bewerkstelligen kann. Blöderweiseweise habe ich "Ja" gesagt, bekomme es jetzt leider doch nicht schnell hin.

Hoffe jmd kann schnell aushelfen^^

Ich soll eine Zeile einlesen (Schlagwort <genre> suchen und danach bestimmte Worte suchen - eigentlich kein Problem und habe ich bereits in frühen Projekten bewältigt, wenn vlt auch nicht grad optimal, aber es funktionierte)

<genre>Action / Fantasy / History / War</genre>


Jetzt muss ich aber für jeden gefunden Begriff ein neue Zeile erstellen und mit genre umschliessem und dies sollte dann eta so aussehen

<genre>Action</genre>
<genre>Fantasy</genre>
<genre>History</genre>
<genre>War</genre>



Ich denke mal für den Profi keine Problem und in paar Zeilen erledigt- für mich scheint es aber schon fast Projektcharakter zu haben:(

Es fängt leider schon dabei an, wie ich die Zeilen am besten unter der gesuchten Zeile einfüge und wie ich die ersetzungen vornehmen muss!
 
Zuletzt bearbeitet:
Ich persönlich würde eine temporäre Datei erstellen und die Quelldatei Zeile für Zeile kopieren, es sei denn du findest eben genannten Fall, dann schreibst du die Zeilen rein, die du neu generierst. Am ende kannst du bei Bedarf die Quelldatei durch die temporäre Datei ersetzen.
 
Hi.

Ich finde man sollte es tunlichst vermeiden temporäre Dateien zu verwenden. Du kannst doch genauso gut die Datei komplett in den Speicher laden. http://www.codeproject.com/Articles/15956/Security-Tips-for-Temporary-File-Usage-in-Applicat

Und die Datei scheint eine XML Datei zu sein? Da könnte man einfach XML Methoden verwenden (SelectElementsByTagName, InnerText) und eben das Dokument in den Speicher laden, verändern und wieder zurückschreiben.

Gruß
 
Schade, scheint wohl doch aufwendiger zu sein ... werde es die nächsten Tage mal angehen. Danke für die Tipps:)

Meine Idee wäre eher dahin gegangen, das ich einfache Replace-Abfragen durchführe:

1. erstmal die "genre"-Zeile suche und schon mal <genre> und </genre> entferne (noch unklar wie ich das anstelle)
2. um jedes gefundene Genre (Zb Action) einfach <genre> vorne und </genre> mit Enter hinten anfüge (unklar wie das "Enter" ausehen muss)

EDIT: Habs mal umgesetzt und passt soweit, zwar nicht schön aber es geht:

Code:
$file = Get-Content $source_file #Datei einlesen
$str | out-file $source_file # Inhalt der Datei löschen 
foreach ($str in $file) 
{ 
	if ($str -like '*genre*') { # SubString ist nicht enthalten; die * sind bedingt erforderlich 
	  $f = $f.Replace("<genre>", "")
	  $f = $f.Replace("</genre>", "")
	  $f = $f.Replace(" / ", "")
	  $f = $f.Replace("Action", "<genre>Action</genre>`n")
	  $f = $f.Replace("Adventure", "<genre>Adventure</genre>`n")
	  $f = $f.Replace("Thriller", "<genre>Thriller</genre>`n")
	  $f = $f.Replace("War", "<genre>War</genre>`n")	
	  $f | out-file $source_file -append 
	} else { 
	  $str | out-file $source_file -append  # SubString ist enthalten -> Zeile wird an die Datei angehängt 
	}	 
}
 
Zuletzt bearbeitet:
Falls es sich wirklich um eine XML Datei handelt, ist es problematisch einfach mit Stringersetzungen zu hantieren, da Leerzeichen in XML keine Bedeutung haben und letztendlich entfernt oder hinzugefügt werden können ohne die Bedeutung zu verändern.

Bsp:

Eingabe:
XML:
<root>
<genre>Action / Fantasy / History / War</genre>
</root>
# powershell

XML:
$xml = gc "./genre.xml"

$genres = $xml.GetElementsByTagName("genre")

foreach ($g in @($genres)) {
  $p = $g.ParentNode
  $p.RemoveChild($g)
  $g.InnerText.Split("/") | foreach {
    $n = $xml.CreateElement("genre")
    $n.InnerText = $_.Trim()
    $p.AppendChild($n)
  }
}

$xml.Save([System.Console]::Out)
Ausgabe:
XML:
<?xml version="1.0" encoding="ibm850"?>
<root>
  <genre>Action</genre>
  <genre>Fantasy</genre>
  <genre>History</genre>
  <genre>War</genre>
</root>
Gruß
 
Zuletzt bearbeitet von einem Moderator:
@deepthroat

Danke, wußte ich doch, das das professioneller geht! Deine Lösung habe ich leider zu spät gesehen und werde diese nun verwenden!

Schönes Wochenende

EDIT: zu früh gefreut, bekomme Fehler:

method on a null-valued expression.

$p.RemoveChild(<<<< $g)


Liegt es an der struktur?

Code:
<?xml version="1.0" encoding="utf-8"?>
<movie xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <genre>Action / Adventure / Thriller / War</genre>
</movie>

Kleiner Tipp wäre toll:-(
 
Zuletzt bearbeitet:
Bist du dir sicher, das du alles richtig übernommen hast?

Für dein Beispiel bekomme ich die Ausgabe:
XML:
<?xml version="1.0" encoding="ibm850"?>
<movie xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <genre>Action</genre>
  <genre>Adventure</genre>
  <genre>Thriller</genre>
  <genre>War</genre>
</movie>
Gruß
 
Zuletzt bearbeitet von einem Moderator:
könnte XP der Grund sein bzw das ich es über eine Batch aufrufe?

Hatte schon mal irgendwo Probleme zwischen Windows 7 und XP ... das ganze wird zwar in einer Funktion aufgerufen, habe das aber zu Testzwecken so vereinfacht, das letztendlich nur dein Code drin stand und es immer noch den Fehler gibt

Fehler:
Code:
You cannot call a method on a null-valued expression.
At E:\Downloads\test\_FilmeTools.ps1:158 char:17
+   $p.RemoveChild( <<<< $g)
You cannot call a method on a null-valued expression.
At E:\Downloads\test\_FilmeTools.ps1:159 char:21
+   $g.InnerText.Split( <<<< "/") | foreach {
<?xml version="1.0" encoding="ibm850"?>
<movie xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
  <genre>Action / Adventure / Thriller / War</genre>
</movie>

Habe es grad mal unter Windows 7 getestet ... dort war keine Fehler und die Ausgabe war in Ordnung. Liegt also an XP!!
 
Zuletzt bearbeitet:
Mit dem OS hat das nicht viel zu tun. Bei mir funktioniert es unter XP problemlos.

Welche Powershell Version hast du denn installiert? Evtl. solltest du auf 2.0 upgraden..
 
Zurück