So hängen Sie eine Zeile, die nicht mit „

So hängen Sie eine Zeile, die nicht mit „

Ich habe ein Protokoll, das XML-Zeilen enthält. Beispielformat unten:

<head>
    <body>
        <line>
asdasd</line>
    </body>
</head>

Ich möchte die Protokolldatei scannen und die Zeilen, die nicht mit „<“ beginnen, an die vorherige Zeile anhängen. Die Ausgabe würde wie folgt aussehen:

<head>
    <body>
        <line>asdasd</line>
    </body>
</head>

Danke

Antwort1

Ich glaube, ich habe das schon einmal gesagt – aber auf die Gefahr hin, mich wie eine kaputte Schallplatte anzuhören – verwenden Sie KEINE regulären Ausdrücke zum Parsen von XML. Das ist brüchig und bricht leicht. Ich würde jedoch zuerst fragen – warum versuchen Sie, das zu tun, was Sie tun? Weil es bei der Arbeit mit Ihrem XML irrelevant sein sollte.

Verwenden Sie stattdessen einen Parser:

#!/usr/bin/env perl
use strict;
use warnings;

use XML::Twig;

my $twig = XML::Twig->parsefile('your_file.xml');

foreach my $elt ( $twig->get_xpath('//#PCDATA') ) {
    $elt->set_text( $elt->trimmed_text );
}

$twig->set_pretty_print('indented_a');
$twig->print;

Dies bewirkt, was Sie möchten. Wenn Sie jedoch normal mit XML arbeiten, trimmed_textist diese Verarbeitung mit dieser Methode wahrscheinlich ohnehin nicht mehr erforderlich.

Antwort2

Perl zur Rettung!

perl -pe 'print "\n" if /^\s*+</; chomp;' input > output

Das heißt, aus jeder Zeile wird ein Zeilenumbruch entfernt und der Text wird gedruckt, wenn die nächste Zeile mit einem Leerzeichen beginnt, gefolgt von einem <.

Um die letzte neue Zeile beizubehalten, ändern Sie sie chompin chomp unless eofoder fügen Sie sie hinzuEND { print "\n" }

Antwort3

Fast standardmäßiges SED-Verfahren

sed '$!N;s/\n\(\s*[^<[:blank:]]\)/\1/;P;D' log.xml

Antwort4

Verwenden der XPath-Funktion normalize-spacezum Entfernen des anfänglichen Zeilenumbruchs des /head/body/lineKnotens:

xmlstarlet edit --update '/head/body/line' --expr 'normalize-space(text())' file.xml

Oder mit Kurznamen:

xmlstarlet ed -u '/head/body/line' -x 'normalize-space(text())' file.xml

Die Ausgabe wäre, angesichts der Eingabe in der Frage,

<?xml version="1.0"?>
<head>
  <body>
    <line>asdasd</line>
  </body>
</head>

Verwenden Sie //lineanstelle des vollständigen Pfads vom Stammknoten, wenn Sie alle lineKnoten in Ihrem Eingabedokument beeinflussen möchten.

Fügen Sie nach -Ooder „ oder“ hinzu, um die Deklaration am Anfang des resultierenden Dokuments zu verwerfen.--omit-decledited<?xml ...>

verwandte Informationen