2

I have the blocks of data which are differentiated by the global Ids as below. I need to extract the last block of data with the highest id value, in the below example, id="82".

<gc type="global" id="80" totalid="80" intervalms="315080.595">
---Remaining data---------
 </gc>
 <gc type="global" id="81" totalid="81" intervalms="315080.595">
---Remaining data---------
 </gc>
 <gc type="global" id="82" totalid="82" intervalms="315080.595">
---Remaining data---------
 </gc>

I can perform the below. However, it will restrict the id value to be two digits only. How can I derive the last block of data without putting the digits restriction on id value.

data1=`grep "gc type="global"" abc.log| cut -c24-26|tail -n1`

lastdata="gc type="global"=$data1"

sed -n '/'"${lastdata}"'/,$p' abc.log>last_block_data.log
  • Are the data formatted in XML? – choroba Jul 31 '15 at 13:14
  • Not sure if I answer it right. The data is a common log file and the content within happens to occur between tags. – alex Jul 31 '15 at 13:21
  • Does xmllint read the file without errors? – choroba Jul 31 '15 at 13:32
  • What if the highest id value is not the last block? Do you always want the last block, whatever its value, or do you always want the highest value, whatever its position? – terdon Jul 31 '15 at 14:30
1

You don't have to cut by -character count. Instead, you can cut on a specified -delimiter.

grep '^<gc type="global"' <infile | cut -d\" -f4

80
81
82

That gets only the 4th "-delimited field on a line. And so that field can be as many characters - or digits if you prefer - as you like, so long as none of them are double-quotes.

But you don't have to do that either if you want the whole line.

sed -e'/^<gc type="global"/!{g;/./q;d;}' -e'h;$!d' <infile
| improve this answer | |
1

Assuming that the data is a properly formatted and well formed XML document, like this

<?xml version="1.0"?>
<root>
  <gc type="global" id="80" totalid="80" intervalms="315080.595">
---Remaining data---------
 </gc>
  <gc type="global" id="81" totalid="81" intervalms="315080.595">
---Remaining data---------
 </gc>
  <gc type="global" id="82" totalid="82" intervalms="315080.595">
---Remaining data---------
 </gc>
</root>

The data for the gc node with an id attribute of 82 may be extracted using XMLstarlet like so:

xmlstarlet sel -t -v '//gc[@id="82"]' file.xml

This would get the contents of the relevant gc node, regardless of where in the document that node happens to be located.

| improve this answer | |
0
awk -F[=\"] '{
    a[FNR]=$0;
    if ($6>l && $0 ~ "<gc type=\"global\""){
        l=$6;f=1;s=FNR
    };
    if($0 ~ "</gc>" && f==1 ){
        e=FNR;f=0
    }}
    END{ 
    for (i=s;i<=e;i++) {
        print a[i]
}}'

This will print the block starts from <gc type="global" till </gc> that has largest id.

All lines are saved to array a with key as FNR

First if will set the flag f and set the array key start variable s to FNR if the 6th field which is id greater than the previous one and the line has string <gc type=\"global\" .

Next if reset the flag and set the the array key end variable e to FNR if the line contans string </gc> and f equal to 1

In the END elements in array a are printed only when the key value between s and e.

| improve this answer | |
  • This doesn't get the block of data. It will only print the <gc... line. The OP wants everything from that line to the </gc> tag. – terdon Jul 31 '15 at 14:32
  • Made changes to print entire block for largest id – jijinp Jul 31 '15 at 17:19
0

You could grep to find the lines with 'type="global"' and then use sed to extract the values within the quotes after 'id=':'

$ grep 'type="global"' /tmp/foo | sed -e 's/^.*id="\([0-9]*\)".*$/\1/'
80
81
82
...
| improve this answer | |

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.