2016-07-14 8 views
0

Es gibt einige Daten (XML) in einer Datei, und ich muss Text entfernen (nicht die ganze Zeile, so/d Option von sed passt nicht) von Substring1 bis zu Substring2 (einschließlich beider) nur, wenn es ein Muster enthält. Mein Problem hier ist, dass es verschiedene Formatierungen geben kann, so dass Substring1 und Substring2 entweder in derselben Zeile oder in einer anderen Zeile sein können, oder dass mehrere Paare von Substrin1/2 in derselben Zeile stehen.Entfernen Sie Text zwischen Teilstrings (egal in der gleichen Zeile oder mehrzeilig), nur wenn es Muster enthält

Beispiel (1. Linie - 2 Paar Substrings1/2 und erste enthält PATTERN, 2. Zeile - 1 Paar mit Muster, 3. Zeile - 1 Paar ohne Muster, 4. und 5. Linien - 1 Paar mit Muster, 6. und 7. Linien - 1 Paar ohne Muster):

Substring1 = <?xml

Substring2 = </update>

Pattern = PATTERN

tmp.log 
<?xml version="1.0" encoding="UTF-8" PATTERN-line1 <upd_date>2016-03-24</upd_date><upd_time>00:01:00.200</upd_time> blah-blah-blah </update><?xml version="1.0" encoding="UTF-8" blah-blah-blah-line1 <upd_date>2016-03-24</upd_date><upd_time>00:01:00.200</upd_time> blah-blah-blah </update> 
<?xml version="1.0" encoding="UTF-8" PATTERN-line2 <upd_date>2016-03-24</upd_date><upd_time>00:01:00.200</upd_time> blah-blah-blah </update> 
<?xml version="1.0" encoding="UTF-8" blah-blah-blah-line3 <upd_date>2016-03-24</upd_date><upd_time>00:01:00.200</upd_time> blah-blah-blah </update> 
<?xml version="1.0" encoding="UTF-8" PATTERN-line4 <upd_date>2016-03-24</upd_date> 
<upd_time>00:01:00.200</upd_time> blah-blah-blah-line5 </update> 
<?xml version="1.0" encoding="UTF-8" blah-blah-blah-line6 <upd_date>2016-03-24</upd_date> 
<upd_time>00:01:00.200</upd_time> blah-blah-blah-line7 </update> 

Expected output: 
<?xml version="1.0" encoding="UTF-8" blah-blah-blah-line1 <upd_date>2016-03-24</upd_date><upd_time>00:01:00.200</upd_time> blah-blah-blah </update> 
<?xml version="1.0" encoding="UTF-8" blah-blah-blah-line3 <upd_date>2016-03-24</upd_date><upd_time>00:01:00.200</upd_time> blah-blah-blah </update> 
<?xml version="1.0" encoding="UTF-8" blah-blah-blah-line6 <upd_date>2016-03-24</upd_date> 
<upd_time>00:01:00.200</upd_time> blah-blah-blah-line7 </update> 

`ve versucht (ohne vollständigen Erfolg) verschiedene Kombinationen wie folgt aus:

sed -i "s#<?xml.*PATTERN.*</update>##g" tmp.log 

sed -i "#<?xml#{p; :a; N; #</update>#!ba; s#.*\n##}; p" tmp.log 

perl -pi -e 's/<?xml.*PATTERN.*update>//' tmp.log 

Soweit ich sehen kann, diese ganze Linien entfernen und überspringen den Fall, wenn Teil auf verschiedenen Linien befinden. Ich führe hier auch keine echte Überprüfung auf PATTERN durch. Jede Hilfe wird geschätzt.

+0

1480 Elemente stimmen mit '[sed] xml' überein, wenn Sie hier suchen. Hast du einen von ihnen angeschaut? Viel Glück. – shellter

+1

Verwenden Sie stattdessen ein XML-fähiges Tool. –

+0

bitte Ihre erwartete Ausgabe – ssr1012

Antwort

2

Mit gawk:

awk -v RS='<\\?xml' 'NR!=1 && !(/PATTERN/){print "<?xml",$0}' 
+0

Danke. Funktioniert. –

0

Bitte versuchen Sie dieses:

use strict; 
use warnings; 

my $newDATA = ""; 
while(<DATA>) 
{ 
    my $each_line = $_; my $dump = $each_line; 
     my ($pre,$match,$post) = ""; 
     while($each_line=~/<\?xml((?:(?!<\?xml|\n).)*)<\/update>/sg) 
     { 
      $pre = $pre.$`; $match=$&; $post = $'; my $dupmatch = $match; 
      if($dupmatch=~m/PATTERN/i) 
      { $match = ""; } 
      $pre = $pre.$match; $each_line = $post; 
     } 
     if(length $pre) { $each_line = $pre.$post; } 
     $newDATA .= $each_line; 
} 
$newDATA=~s/\n{,1}/\n/g; 
print $newDATA; 

INPUT:

__DATA__ 
<?xml version="1.0" encoding="UTF-8" PATTERN-line1 <update>2016-03-24</update><upd_time>00:01:00.200</upd_time> blah-blah-blah </update><?xml version="1.0" encoding="UTF-8" blah-blah-blah-line1 <update>2016-03-24</update><upd_time>00:01:00.200</upd_time> blah-blah-blah </update> 
<?xml version="1.0" encoding="UTF-8" PATTERN-line2 <update>2016-03-24</update><upd_time>00:01:00.200</upd_time> blah-blah-blah </update> 
<?xml version="1.0" encoding="UTF-8" blah-blah-blah-line3 <update>2016-03-24</update><upd_time>00:01:00.200</upd_time> blah-blah-blah </update> 
<?xml version="1.0" encoding="UTF-8" PATTERN-line4 <update>2016-03-24</update> 
<upd_time>00:01:00.200</upd_time> blah-blah-blah-line5 </update> 
<?xml version="1.0" encoding="UTF-8" blah-blah-blah-line6 <update>2016-03-24</update> 
<upd_time>00:01:00.200</upd_time> blah-blah-blah-line7 </update> 

OUTPUT:

<?xml version="1.0" encoding="UTF-8" blah-blah-blah-line1 <update>2016-03-24</update><upd_time>00:01:00.200</upd_time> blah-blah-blah </update> 
<?xml version="1.0" encoding="UTF-8" blah-blah-blah-line3 <update>2016-03-24</update><upd_time>00:01:00.200</upd_time> blah-blah-blah </update> 
<upd_time>00:01:00.200</upd_time> blah-blah-blah-line5 </update> 
<?xml version="1.0" encoding="UTF-8" blah-blah-blah-line6 <update>2016-03-24</update> 
<upd_time>00:01:00.200</upd_time> blah-blah-blah-line7 </update> 

Ihre XML-Markierung ist sehr inkonsistent. Könnten Sie bitte überprüfen und die obige Perl-Codierung.

1

Wenn es tatsächlich noch mehr von diesem bitte verwenden Sie die guten Module für XML. Sowohl XML::libXML als auch sind hervorragend. Das heißt, hier ist das direkte Parsen.

use warnings; 
use strict; 

# Sample text for testing 
my $text = q(start <?xml with PATTERN yes </update> and <?xml good </update> end); 

my $beg = qr(<\?xml); 
my $end = qr(</update>); 
my $patt = qr(PATTERN); 

$text =~ s|$beg.*?$patt.*?$end||gs; 

print "$text\n"; 

Die .*? ist nicht gierig. Die Zeilenumbrüche werden mit dem Modifikator erledigt, der . entspricht. Da der Text in der Frage zu mir unklar ist, habe ich die $text oben als Eingabe verwendet:

start <?xml with PATTERN yes </update> and <?xml good </update> end 

Mit diesem Eingang in $text der oben genannten Code druckt

start and <?xml good </update> end