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

Diskutiere [Gelöst] Suchen und ersetzen mit Hilfe mehrerer Parameter im Shell-Skripte Forum im Bereich Programmieren unter Linux/Unix; 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...

  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. marce

    marce Kaiser

    Dabei seit:
    01.08.2007
    Beiträge:
    1.155
    Zustimmungen:
    15
    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.
     
  3. 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
     
  4. marce

    marce Kaiser

    Dabei seit:
    01.08.2007
    Beiträge:
    1.155
    Zustimmungen:
    15
    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.
     
  5. 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] 2.HDD unter Freebsd partitionieren

    [gelöst] 2.HDD unter Freebsd partitionieren: Hallo Habe eine Testserver mit freeBSD 11.0 auf einer IDE-HDD (ada0) mit ZFS-root hab jetzt eine 2. HDd (SATA) angeschlossen und wollte die...
  2. [gelöst] - for file in ... nur für bestimmte Endungen?

    [gelöst] - for file in ... nur für bestimmte Endungen?: Hallo Zusammen Ich habe einen eigenen Server und das Ziel mittels einem Shell-Skript ein Verzeichnis auf neue Dateien zu überprüfen. Das Skript...
  3. [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:...
  4. [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...
  5. [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...