-2

this is my input file

<MessageOut>
<Attribute name="Session-Id" value="22250"/><Attribute name="CC-Request-Type" value="2"/><Attribute name="CC-Request-Number" value="1"/><Attribute name="Origin-Host" value="indlnqw291"/><Attribute name="Origin-Realm" value="amdocs.com"/><Attribute name="Auth-Application-Id" value="4"/><Attribute name="Result-Code" value="5031"/><Attribute name="CC-Session-Failover" value="1"/><Attribute name="Low-Balance-Indication" value="0"/><Attribute name="Multiple-Services-Credit-Control"><Group><Attribute name="Result-Code" value="5031"/><Attribute name="Service-Identifier" value="0"/><Attribute name="Rating-Group" value="2"/></Group></Attribute></MessageOut>
<MessageOut>
<Attribute name="Session-Id" value="22250"/><Attribute name="CC-Request-Type" value="3"/><Attribute name="CC-Request-Number" value="2"/><Attribute name="Origin-Host" value="indlnqw291"/><Attribute name="Origin-Realm" value="amdocs.com"/><Attribute name="Auth-Application-Id" value="4"/><Attribute name="Result-Code" value="5031"/></MessageOut>
<MessageOut>
<Attribute name="Session-Id" value="22250"/><Attribute name="CC-Request-Type" value="1"/><Attribute name="CC-Request-Number" value="0"/><Attribute name="Origin-Host" value="indlnqw291"/><Attribute name="Origin-Realm" value="amdocs.com"/><Attribute name="Auth-Application-Id" value="4"/><Attribute name="Result-Code" value="5031"/><Attribute name="CC-Session-Failover" value="1"/><Attribute name="Low-Balance-Indication" value="0"/><Attribute name="Multiple-Services-Credit-Control"><Group><Attribute name="Result-Code" value="5031"/><Attribute name="Service-Identifier" value="0"/><Attribute name="Rating-Group" value="2"/></Group></Attribute></MessageOut>

i want grep result code after "Multiple-Services-Credit-Control"

expected result:

"CC-Request-Type" value="1"
"CC-Request-Number" value="0"
"Result-Code" value="5031"

"CC-Request-Type" value="2"
"CC-Request-Number" value="1"
"Result-Code" value="5031"

"CC-Request-Type" value="3"
"CC-Request-Number" value="2"
"Result-Code" value="5031"

thanks in advance

Andy Lester
  • 91,102
  • 13
  • 100
  • 152
velu
  • 3
  • 1
  • 5
    You tagged this with `sed` and `grep`, but neither of these tools were designed to handle structured markup, which is generally too complex for standard unix filters. While your specific use case *might* be doable, I'd probably just use an XML parsing library from your favorite language – gardenhead Aug 22 '16 at 18:23
  • 2
    Have you tryed anything so far? SO is not a place for I have this, I expect this and wait for it to happen'. Please post what you've tryed. – John Doe Aug 23 '16 at 11:52
  • i tried with below cmd it working fine if i grep singe message out session but i can't use for 3 session sed -n -e 's/^.*Multiple-Services-Credit-Control//p' xml.txt | sed -n -e 's/^.*Result-Code" value=//p' | cut -d'"' -f2 – velu Aug 23 '16 at 12:49
  • Why not create a Perl script and read data line by line? – John Doe Aug 23 '16 at 13:50
  • actually i'm not aware perl , please suggest me which one is best perl, unix or xmllint for this job – velu Aug 23 '16 at 13:59
  • Any tool that supports xpath should do the job –  Aug 23 '16 at 14:19

2 Answers2

2

This is XML. It's a bad idea to try and use regular expressions on XML, because XML is contextual, and regular expressions aren't.

Use an XML Parser. Most will let you do xpath which is comparable to regular expressions - but specifically designed to handle the contextual nature of XML.

perl has multiple options. I like XML::Twig particularly.:

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

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

my @attributes = qw ( CC-Request-Type CC-Request-Number Result-Code );

foreach my $msg ( $twig -> get_xpath('//MessageOut') ) {
    foreach my $attribute ( @attributes ) {
        print "$attribute value=",$msg -> get_xpath("//Attribute[\@name=\'$attribute\']",0)->att('value'),"\n"; 
    }
    print "\n";
}

With your sample data (slightly amended to include root tags) give:

CC-Request-Type value=2
CC-Request-Number value=1
Result-Code value=5031

CC-Request-Type value=2
CC-Request-Number value=1
Result-Code value=5031

CC-Request-Type value=2
CC-Request-Number value=1
Result-Code value=5031
Community
  • 1
  • 1
Sobrique
  • 52,974
  • 7
  • 60
  • 101
  • Good asnwer. I was using the "line pattern" from the question, but this is working in all contexts. – John Doe Aug 23 '16 at 14:19
  • Yes. I didn't downvote it, because it does solve the problem, but I honestly believe that regexing XML is creating future problems. – Sobrique Aug 23 '16 at 14:31
0
use strict;
use warnings;

my $filename = 'path_to_input_file\data.txt';
open(my $fh, '<:encoding(UTF-8)', $filename)
or die "Could not open file '$filename' $!";

while (my $row = <$fh>) {
    chomp $row;
    $row =~ /.*?("CC-Request-Type"\svalue="\d*").*?("CC-Request-Number"\svalue="\d*").*?("Result-Code" value="\d*")/;
    if ( (defined $1) and (defined $2) and (defined $3)){
        print "\n$1\n$2\n$3\n";
    }
}

This is the solution in Perl. If you need explanations for the reg-ex used I will gladly exlpain it.

John Doe
  • 1,058
  • 8
  • 30
  • Yes, the script will read each line from the input file. After that it will search for the pattern. I used groups to catch the information, what you see inside the paranthesses, those are groupings. ` $_ ` will store the information in the order of the paranthesses from left to right. – John Doe Aug 29 '16 at 09:33