[Gelöst] Suchen und ersetzen mit Hilfe mehrerer Parameter

Dieses Thema im Forum "Shell-Skripte" wurde erstellt von Jacko, 17.05.2016.

  1. Jacko

    Jacko Grünschnabel

    Dabei seit:
    17.05.2016
    Beiträge:
    3
    Zustimmungen:
    0
    Hallo zusammen,

    ich bin an einem Punkt angekommen, wo ich nicht mehr weiter komme und hoffe ihr könnt mir weiter helfen.
    Anbei ein Ausschnitt aus einer xml Datei:

    Code:
    <Position>
            <SKU>A/370269/10432/32D</SKU>
            <Batch>00320160501</Batch>
            <Description>Carlotta</Description>
            <Amount>1</Amount>
            <ForeignPos1>172991</ForeignPos1>
            <ForeignPos2>10</ForeignPos2>
            <Positionreferences>
              <PosReference number="1"/>
              <PosReference number="2"/>
              <PosReference number="3">0</PosReference>
              <PosReference number="4">0</PosReference>
              <PosReference number="5"/>
              <PosReference number="6">370269</PosReference>
              <PosReference number="7">10432</PosReference>
              <PosReference number="8">pearl grey</PosReference>
              <PosReference number="9"/>
              <PosReference number="10"/>
              <PosReference number="11">26 INCH</PosReference>
            </Positionreferences>
    </Position>
    <Position>
            <SKU>A/370269/10432/32D</SKU>
            <Batch>00520160501</Batch>
            <Description>Carlotta</Description>
            <Amount>6</Amount>
            <ForeignPos1>172992</ForeignPos1>
            <ForeignPos2>10</ForeignPos2>
            <Positionreferences>
              <PosReference number="1"/>
              <PosReference number="2"/>
              <PosReference number="3">0</PosReference>
              <PosReference number="4">0</PosReference>
              <PosReference number="5"/>
              <PosReference number="6">370269</PosReference>
              <PosReference number="7">10432</PosReference>
              <PosReference number="8">pearl grey</PosReference>
              <PosReference number="9"/>
              <PosReference number="10"/>
              <PosReference number="11">26 INCH</PosReference>
            </Positionreferences>
    </Position>
    Im Moment nutze ich ein Skript, dass mir die beiden Zeilen mit den Referenzen 9 & 10 mit Hilfe von einem übergebenem Parameter verändert. Aufruf erfolgt mit z.B.
    Code:
    vtqichange test.xml 4711/0815
    Code:
    #!/bin/bash
    
    if [ $# -lt 2 ] ; then
            echo "Usage: `basename $0` <Filename> <Datafield8>"
    else
            # initialize variable for filename
                file=$1
    
            # convert xml file in readable format
               xmllint --format $file > $file.tmp
    
            # split string from $2 in seperate variables
                IFS="/"
                Wert=$2
                set -- $Wert
                p9=$2
                p10=$1
    
            # simple sed replace but output to a new file
                sed 's@NEW@UPD@' $file.tmp > $file.tmp2
                sed 's@<PosReference number="9"/>@<PosReference number="9">'$p9'</PosReference>@' $file.tmp2 > $file.tmp3
                sed 's@<PosReference number="10"/>@<PosReference number="10">'$p10'</PosReference>@' $file.tmp3 > $file.tmp4
    
            # append prefix from original file name with "_script"
    
                new=`echo $file | sed 's@.xml@_script.xml@'`
    
            # check if $new is empty or not
                if [ -z "$new" ]
                  then
                    :
                  else
                    cp $file.tmp4 $new
                fi
    
            # delete all temporary files
                rm -f $file.tmp $file.tmp2 $file.tmp3 $file.tmp4
    fi
    Im Anschluss sehen alle Zeilen mit Ref 9 & 10 wie folgt aus:
    Code:
              <PosReference number="9">0815</PosReference>
              <PosReference number="10">4711</PosReference>
    
    Solange die Batch Nummer in der Datei überall gleich ist, reicht mir ein Parameter. Jedoch kommt es häufig vor, dass die Batch Nummer verschieden ist (siehe auch Beispiel oben) und demnach auch die Werte in Ref 9 & 10.
    Nun würde ich gerne wissen, ob und vielleicht wie es möglich ist, mehrere Werte gleichzeitig zu ändern, je nachdem welche Batch Nummer man mit übergibt.

    Dachte an einen Aufruf wie z.B.:
    Code:
    basename $0 <Filename> <batch#1> <parameter#1> <batch#2> <parameter#2> <batch#3> <parameter#3>
    
    Das Skript sucht die gesamte Datei nach dem Wert batch#1 geht immer 14 bzw. 15 Zeilen runter und ändert dort den Wert für Ref 9 & 10 nach Vorgabe parameter#1. Das selbe dann für batch#2, batch #3 etc.

    Hat jemand eine Idee?

    Danke und Gruß
    Jacko
     
  2. Anzeige

    Schau dir mal diese Kategorie an. Dort findest du bestimmt etwas.
    Registrieren bzw. einloggen, um diese und auch andere Anzeigen zu deaktivieren
  3. marce

    marce Kaiser

    Dabei seit:
    01.08.2007
    Beiträge:
    1.054
    Zustimmungen:
    8
    geht problemlos - Du kannst ja auch die anderen Bereich in der RegEx mit Variablen erweitern.

    Grundlegend würde ich Dir aber empfehlen, das nicht mit sed zu machen sondern dafür einen ded. xml-Bibliothek zu verwenden, in der Du ded. auf die einzelnen Elemente zugreifen kannst - php, perl können das wesentlich besser, auch für python oder andere Scriptsprachen findet sich sicher was.
     
  4. Jacko

    Jacko Grünschnabel

    Dabei seit:
    17.05.2016
    Beiträge:
    3
    Zustimmungen:
    0
    Hallo marce,

    habe bis dato noch nie ein Perl, Python o.ä. Skript erstellt. Von daher konnte ich nicht wirklich was mit deinem Beitrag anfangen. Habe mir jetzt mal auf die schnelle ein paar Perl Basics rausgesucht und folgendes Skript erstellt:

    Code:
    #!/usr/local/bin/perl -w
    
    use strict;
    use warnings;
    use Tie::File;
    
    my $inputfile = $ARGV[0];
    my $batch1 = $ARGV[1];
    my $param1 = $ARGV[2];
    my $batch2 = $ARGV[3];
    my $param2 = $ARGV[4];
    my $arg_count = scalar @ARGV;
    
    my @ref1;
    my @ref2;
    
    @ref1 = split(/\//, $param1);
    if ($arg_count == 5) { @ref2 = split(/\//, $param2); }
    
    my @records;
    tie @records, 'Tie::File', $inputfile;
    
    my $last_idx = $#records;
    
    for (0 .. $last_idx) {
       if ($records[$_] =~ /$batch1/) {
          print "Vorher --> $records[$_+15]\n";
          $records[$_+15] =~ s@<PosReferenz nummer="9"/>@<PosReferenz nummer="9">$ref1[1]</PosReferenz>@g;
          print "Nachher --> $records[$_+15]\n";
    
          print "Vorher --> $records[$_+16]\n";
          $records[$_+16] =~ s@<PosReferenz nummer="10"/>@<PosReferenz nummer="10">$ref1[0]</PosReferenz>@g;
          print "Nachher --> $records[$_+16]\n";
    
          print "\n";
       }
    
       if ($records[$_] =~ /$batch2/) {
          print "Vorher --> $records[$_+15]\n";
          $records[$_+15] =~ s@<PosReferenz nummer="9"/>@<PosReferenz nummer="9">$ref2[1]</PosReferenz>@g;
          print "Nachher --> $records[$_+15]\n";
    
          print "Vorher --> $records[$_+16]\n";
          $records[$_+16] =~ s@<PosReferenz nummer="10"/>@<PosReferenz nummer="10">$ref2[0]</PosReferenz>@g;
          print "Nachher --> $records[$_+16]\n";
    
          print "\n";
       }
    }
    
    untie @records;
    
    Ein Aufruf mit z.B.
    Code:
    perl test.pl myfile.xml 00320160501 0815/4711 00120160501 1234/5678
    klappt ohne Probleme, jedoch habe ich noch ein paar kleinere Frage, die ich noch nicht gelöst bekommen habe.

    1. Im Moment wird die Eingangsdatei überschrieben, möchte aber die Änderungen unter einem neuen Namen (myfile_change.xml) speichern. Wie geht das?

    2. Ich möchte folgende Zeile
    Code:
    xmllint --format $inputfile
    aus dem Shellskript auch unter Perl ausführen. Wie kann ich Bash Befehle unter Perl implementieren?

    3. Folgende Codezeilen funktionieren anscheinend ohne Probleme:
    Code:
    @ref1 = split(/\//, $param1);
    if ($arg_count == 5) { @ref2 = split(/\//, $param2); }
    
    Ändere ich die erste Zeile auf
    Code:
    if ($arg_count == 3) { @ref1 = split(/\//, $param1); }
    
    erhalte ich folgende Fehlermeldungen:
    Use of uninitialized value $ref1[1] in concatenation (.) or string at cbrperl.pl line 36, <$fh> line 553.
    Use of uninitialized value $ref1[0] in concatenation (.) or string at cbrperl.pl line 40, <$fh> line 554.

    Wieso funktioniert die If-Prüfung nicht für ref1?

    Gruß
    Jacko
     
  5. marce

    marce Kaiser

    Dabei seit:
    01.08.2007
    Beiträge:
    1.054
    Zustimmungen:
    8
    Hm, ich meinte eigentlich nicht, Du sollst das Script 1:1 von Shell-Code in Perl-Code übersetzen.

    Du sollst eine Bibliothek verwenden, welche direkt in den XML-Strukturen arbeitet.
     
  6. Jacko

    Jacko Grünschnabel

    Dabei seit:
    17.05.2016
    Beiträge:
    3
    Zustimmungen:
    0
    Na ja, mit der Umwandlung in Perl hat das ja auch ganz gut funktioniert ;)
    Wenn ich noch die drei Punkte gelöst bekomme, speziell 1 und 2, dann bin ich auch zufrieden und habe nebenbei noch ein wenig Perl gelernt :)
     
Thema:

[Gelöst] Suchen und ersetzen mit Hilfe mehrerer Parameter

Die Seite wird geladen...

[Gelöst] Suchen und ersetzen mit Hilfe mehrerer Parameter - Ähnliche Themen

  1. [Gelöst] PostScript-Probleme

    [Gelöst] PostScript-Probleme: Drucker: Kyocera Mita FS-1010 Cups: 2.1 PPD: Kyocera Mita FS-1010 (German) Fehlerausgabe beim Drucken der Testseite (Druckausgabe): ERROR:...
  2. [gelöst] Sortierung von Zeilen

    [gelöst] Sortierung von Zeilen: Hallo, ich habe eine Datei deren Zeilen neu sortiert werden sollen. In der Datei liegen zeilenweise Einträge in 4er Blöcken. 1 text1 2...
  3. [GELÖST] Ausgabeumleitung erweitert - alles in eine Zeile bringen

    [GELÖST] Ausgabeumleitung erweitert - alles in eine Zeile bringen: Hallo Gemeinde, ich habe ein recht triviales SetUp, eine Ausgabeumleitung in Bsp. test.log echo $VAR1 $VAR2.. >test.log Nun kommen direkt...
  4. Assistent erster Start lässt sich nicht beenden [gelöst]

    Assistent erster Start lässt sich nicht beenden [gelöst]: Hallo, habe mir hier gerade den Rechnet neu afgesetzt mit Mandriva 2010. Am Anfang (beim ersten Start) kommt ja immer ein Assistent, der ein...
  5. [gelöst]ksnapshot und kubuntu 9.04

    [gelöst]ksnapshot und kubuntu 9.04: Hallo Leute, Ich habe vor kurzem von 7.10 auf 9.04 mit KDE umgestellt, früher hatte ich unter Druck das schöne Programm ksnapshot. Das tut...