match a pattern and print the line once

Hi,

I have a xml file

 
<cisco:name>
  <cisco:mdNm>Cisco Device 7500 A Series</cisco:mdNm>
  <cisco:meNm>10.1.100.19</cisco:meNm>
  <cisco:ehNm>/shelf=1</cisco:ehNm>
      <cisco:subname>
 <cisco:meNm>10.1.100.19</cisco:meNm>
<cisco:sptp>Cisco PortA Series</cisco:sptp>
         <cisco:aliasNameList xsi:nil="true"/>
         <cisco:owner xsi:nil="true"/>
                      <cisco:subportname>
<cisco:meNm>10.1.100.19</cisco:meNm>
<cisco:meNm>10.1.100.19</cisco:meNm>
                 <cisco:cpt>Cisco SubPort B Series</cisco:cpt>
                 <cisco:aliasNamesubList xsi:nil="true"/>
                 <cisco:userLabel xsi:nil="true"/>
               </cisco:subportname>
       </cisco:subname>
           <cisco:subname>
         <cisco:sptp>Cisco PortAB Series</cisco:sptp>
         <cisco:aliasNameList xsi:nil="true"/>
         <cisco:owner xsi:nil="true"/>
                      <cisco:subportname>
                 <cisco:cpt>Cisco SubPort AB Series</cisco:cpt>
                 <cisco:aliasNamesubList xsi:nil="true"/>
                 <cisco:userLabel xsi:nil="true"/>
               </cisco:subportname>
       </cisco:subname>
</cisco:name>
<cisco:name>
  <cisco:mdNm>Cisco Device 7500B Series</cisco:mdNm>
  <cisco:meNm>10.1.100.20</cisco:meNm>
  <cisco:ehNm>/shelf=2</cisco:ehNm>
      <cisco:subname>
         <cisco:sptp>Cisco Port B Series</cisco:sptp>
         <cisco:aliasNameList xsi:nil="true"/>
         <cisco:owner xsi:nil="true"/>
                      <cisco:subportname>
                 <cisco:cpt>Cisco SubPort B Series</cisco:cpt>
                 <cisco:aliasNamesubList xsi:nil="true"/>
                 <cisco:userLabel xsi:nil="true"/>
               </cisco:subportname>
       </cisco:subname>
</cisco:name>

i want to print once the line where it matches the pattern <cisco:cpt> like
"10.1.100.19 ".

while($0 !~ "</cisco:subname>")
{
getline;
if($0 ~ "<cisco:meNm>/") {print substr($1,13,12)}

}' *.xml

then it print

"10.1.100.19" 4 times. So how can i print only once. Plz suggest

and this series is repeatable and the search the pattern till it find </cisco:subname>

Try:

awk '/cisco:subname/,/\/cisco:subname/ { if ($0 ~ /cisco:meNm/) { print substr($0,13,index($0,"</")-13); exit; } } ' filename

hi,

Actually my code is like

awk '/<cisco:name>/ {
cpt=0
sptp=0
while($0 !~ "</cisco:name>")
{
getline;
if($0 ~ "<cisco:meNm>") {print substr($1,13,11)}
if($0 ~ "<cisco:cpt>") cpt++;
if($0 ~ "<cisco:sptp>") sptp++;
}
print "cpt="cpt
print "sptp="sptp }' test.xml

and output comes as

10.1.100.19
10.1.100.19
10.1.100.19
10.1.100.19
cpt=2
sptp=2
10.1.100.20
cpt=1
sptp=1

But i need as

10.1.100.19
cpt=2
sptp=2
10.1.100.20
cpt=1
sptp=1

---------- Post updated at 08:08 AM ---------- Previous update was at 08:05 AM ----------

hi Jacob,

this individual code works but i have few if condition below . so after exit it wont go for next condition

Your code looks familiar to me. :slight_smile: Change the below line...

if($0 ~ "<cisco:meNm>") {S=substr($1,13,11); if(S!=prevS && S!="") {print S;S=prevS}}
and type 
prevS="" after cpt=0

I could not verify this code, so please look for { } and ()

You can simply pipe your ouput to "uniq" and it would be fine !

still i am getting the same result

10.1.100.19
10.1.100.19
10.1.100.19
10.1.100.19
cpt=2
sptp=2
10.1.100.20
cpt=1
sptp=1

Ok, let me check,
Why I am not suggesting you uniq or sort, is because it may strip other lines too.

could u give an example

Did some silly error...coz could not check the code...
Try this:

if($0 ~ "<cisco:meNm>") {S=substr($1,13,11); if(S!=prevS) print S ;prevS=S}

Thanks rakesh. its now ok.:b:

rakeshawasthi is right, "uniq" may strip other lines. Actually, "uniq" report or omit repeated lines, so if you are curious ^_^, you can try:

awk '.....' test.xml | uniq 

an associative array works quite well for this type of exercise

{
  x=substr($0,13,11)
  hit[x]=1
}
END {
   for(i in hit) {
    print i
    }
}