2

I have a log which contains XML lines. Sample format below:

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

I want to scan the log file and append the lines that do not start with '<' to the previous line. Output would be like below:

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

Thanks

2

Perl to the rescue!

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

i.e. newline is removed from each line, and it's printed when the next line starts with whitespace followed by a <.

To keep the final newline, change chomp to chomp unless eof or add END { print "\n" }

  • 1
    Listen to @Sobrique: use an xml parser for this. It will help you immensely in the future. – cristi Nov 17 '15 at 14:56
2

I think I've said this before - but at risk of sounding like a stuck record - DON'T use regular expressions to parse XML. It's brittle and prone to breaking. I would ask first though - why are you trying to do what you're doing? Because it should be irrelevant when working with your XML.

Instead use a 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;

This does what you want... but if you're actually working with the XML normally, that trimmed_text method probably removes the need for this processing anyway.

  • I can't vote today anymore, but I wanted to say thet this is the correct answer. – cristi Nov 17 '15 at 14:55
1

Almost standard sed procedure

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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.