I have a text file as below.

1001=<?xml ns=dkfj><home><taga>dkjf</taga></home>1002=<?xml ns=dkfj><home1><taga>dkjf</taga></home1>

I need a result as below.

 <?xml ns=dkfj><home><taga>dkjf</taga></home>

 <?xml ns=dkfj><home1><taga>dkjf</taga></home1>

I tried with sed, start and end pattern, but it's not working since both are on the same line.

How can I do it?

  • corrected the output format. I have tried sed -n '/<?xml/,/home>/p' filename – Spike Nov 9 '15 at 20:05
  • Now I really don't understand what you need. You want each XML snippet extracted as-is and output on its own line? How do you know where the XML tree ends? Can we assume it is (\d+=<xml string...>)(\d+=(xml string)* ? – Otheus Nov 9 '15 at 20:22
  • Are you sure that's your XML? Because it ... isn't. It looks like XML, but it's invalid. Is that a transposition error? – Sobrique Nov 9 '15 at 21:19

The original question would be solved by
cat test.xml | tr "<" "\n" | sed -n '/taga>./p' | sed 's/taga>//'
the second, current question would be solved with
cat test.xml | sed 's/[0-9][0-9][0-9][0-9]=/\n/g'

it looks for an occurence of four numbers followed by an = sign, so if you might have those kinds of characters in other places in the real string it wont work, but it doesn't look like that right now


Looking at your snippet, it looks like you've got XML delimited by 'number='. So extract with split:

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

use Data::Dumper;

local $/;
my @xml_chunks = split ( /\d+\=/, <> );
print Dumper \@xml_chunks;

Of course, you should probably note - your XML ... isn't. The declaration isn't valid. I'm going to assume that's a transposition error though. But it should be something like:

<?xml version="1.0" encoding="utf-8"?>

So with your sample data, this will do a reasonable approximation of fixing the XML (assuming of course it isn't valid).

#!/usr/bin/env perl
use strict;
use warnings;
use XML::Twig;
use Data::Dumper;

local $/;
my @xml_chunks = split( /\d+\=/, <DATA> );
print Dumper \@xml_chunks;

foreach my $chunk ( grep {/xml/} @xml_chunks ) {
    $chunk =~ s/^<[^>]+>//;
    my $twig = XML::Twig->new( pretty_print => 'indented_a' );
    $twig->root->set_att( 'xmlns', 'http://www.some_ns.com' );
  • you forgot to comment out your Data::Dumper debugging print. but +1 anyway for being the only answer to use an XML parser rather than trying to do it with regular expressions. – cas Nov 9 '15 at 21:35

I think sed will work, but I'll do a perl solution:

 perl -ane 'while (/(<\?xml.*?>)($|\d+=)/g) { push @w,$1; }' \
        -e 'print join("\n",@w)."\n";@w=();'

The /g regex op in perl says "start the next regex match from here in the line". If there is no match, the regex returns 0 (false), ending the while loop, allowing the codon to print your output. Meanwhile, matches are accumulated in the array @w, which you must clear for the next input line. In the regexp, I'm assuming your search boundary is essentially the digits and equal sign.

  • thanks. I have updated the output format. I need the output as per updated one. – Spike Nov 9 '15 at 20:08

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.