
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_text
ist 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 chomp
in chomp unless eof
oder 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-space
zum Entfernen des anfänglichen Zeilenumbruchs des /head/body/line
Knotens:
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 //line
anstelle des vollständigen Pfads vom Stammknoten, wenn Sie alle line
Knoten in Ihrem Eingabedokument beeinflussen möchten.
Fügen Sie nach -O
oder „ oder“ hinzu, um die Deklaration am Anfang des resultierenden Dokuments zu verwerfen.--omit-decl
edit
ed
<?xml ...>