1

I have input like this:

"[0|0|{A=145,B=2,C=12,D=18}|!][0|0|{A=167,B=2,C=67,D=17}|.1iit][196|0|{A=244,B=6,C=67,D=12}|10:48AM][204|0|{A=9,B=201,C=61,D=11}|Calculator][66|0|{A=145,B=450,C=49,D=14}|phone]0|0|{A=145,B=2,C=12,D=18}|!0|0|{A=167,B=2,C=67,D=17}|.1iit196|0|{A=244,B=6,C=67,D=12}|10:48AM204|0|{A=9,B=201,C=61,D=11}|Calculator66|0|{A=145,B=450,C=49,D=14}|phone";

It appears as a continuous line, there are no line breaks. I need the largest value out of the values between [ and the first occurrence of |. In this case, for example, the largest value is 204. Once that is obtained, I want to print the contents of that element between []. In this case, it would be "204|0|{A=9,B=201,C=61,D=11}|Calculator".

I've tried something like this, but it is not going anywhere:

my @array1;

my $data =  "[0|0|{A=145,B=2,C=12,D=18}|!][0|0|{A=167,B=2,C=67,D=1
+7}|.1iit][196|0|{A=244,B=6,C=67,D=12}|10:48AM][204|0|{A=9,B=201,C=61,
+D=11}|Calculator][66|0|{A=145,B=450,C=49,D=14}|phone]0|0|{A=145,B=2,C
+=12,D=18}|!0|0|{A=167,B=2,C=67,D=17}|.1iit196|0|{A=244,B=6,C=67,D=12}
+|10:48AM204|0|{A=9,B=201,C=61,D=11}|Calculator66|0|{A=145,B=450,C=49,
+D=14}|phone";

my $high = 0;
my @values = split(/\[([^\]]+)\]/,$data) ;
print "Values is @values \n";

foreach (@values) {
    # I want the value that preceeds the first occurence of | in each array
    # element, i.e. 0,0,196,204, etc.
    my ($conf,$rest)= split(/\|/,$_);
    print "Conf is $conf \n";
    print "Rest is $rest \n";
    push(@array1, $conf);
    push (@array2, $rest);
    print "Array 1 is @array1 \n";
    print "Array 2 is @array2 \n";
}

$conf = highest(@array1);
my $i=0;

# I want the index value of the element that contains the highest conf value,
# in this case 204.

for (@myarray1) { last if $conf eq $_; $i++; };
print "$conf=$i\n";

# I want to print the rest of the string that was split in  the same index
# position.

$rest = @array2[$i];
print "Rest is $rest \n";

# To get the highest conf value

sub highest {
    my  @data = @_;
    my $high = 0;
    for(@data) {
        $high = $_ if $_ > $high;
    }
    $high;
}

Maybe I should be using a different approach. Could someone help me, please?

4 Answers 4

1

One way of doing it:

#!/usr/bin/perl

use strict;

my $s = "[0|0|{A=145,B=2,C=12,D=18}|!][0|0|{A=167,B=2,C=67,D=17}|.1iit][196|0|{A=244,B=6,C=67,D=12}|10:48AM][204|0|{A=9,B=201,C=61,D=11}|Calculator][66|0|{A=145,B=450,C=49,D=14}|phone]";

my @parts = split(/\]/, $s);

my $max = 0;
my $data = "";
foreach my $part (@parts) {
    if ($part =~ /\[(\d+)/) {
        if ($1 > $max) {
            $max = $1;
            $data = substr($part, 1);
        }
    }
}
print $data."\n";

A couple of notes:

  • you can split your original string by \], so you get parts like [0|0|{A=145,B=2,C=12,D=18}|!

  • then you parse each part to get the integer after the initial [

  • the rest it's easy: keep track of the biggest integer and of the corresponding part, and output it at the end.

Sign up to request clarification or add additional context in comments.

3 Comments

Sorry for the late response..was sick for a while.. This code worked like charm....thanks so much..
Hi marcoS..though this code works perfect when there are whole numbers.. the max is returned perfectly.. but if there's something like [0.98736|0|{A=145,B=2,C=12,D=18}|!][0.67826|0|{A=167,B=2,C=67,D=17}|.1iit][0.76543|0|{A=244,B=6,C=67,D=12}|10:48AM][0.7775|0|{A=9,B=201,C=61,D=11}|Calculator][0.999|0|{A=145,B=450,C=49,D=14}|phone]" .. in this case i dont get the values correctly..
@MarsMax: sorry for the late response. My code works only for integers. If you want to parse decimal numbers, then you should change the regex /\[(\d+)/ with /\[(\d+(\.\d+)?)/. I haven't test this, but it should work.
0

In shell script:

#!/bin/bash                                                                     

MAXVAL=$(cat /tmp/data | tr [ "\\n" | cut -d"|" -f1 | sort -n | tail -1)
cat /tmp/data | tr [] "\\n" | grep ^$MAXVAL

The first line cuts your big mass of data into lines, extracts just the first field, sorts it and takes the max. The second line cuts the data into lines again and greps for that max val.

If you have a LOT of data, this could be slow, so you could put the "lined" data into a temp file or something.

Comments

0

split() is the Right Tool when you know what you want to throw away. Capturing or m//g is the Right Tool when you know what you want to keep. (paraphrased from a Randal Schwartz quote).

You want to specify what to keep (between square brackets) rather than what to throw away (nothing!).

Luckily, your data is "hash shaped" (ie. alternating keys and values), so load it into a hash, sort the keys, and output the value for the highest key:

my %data = $data =~ /\[
                       (\d+)      # digits are the keys
                       ([^]]+)    # rest are the values
                     \]/gx;
my($highest) = sort {$b <=> $a} keys %data; # inefficent if $data is big
print $highest, $data{$highest}, "\n";

Comments

0

Another way of doing this :

#!/usr/bin/perl

use strict;

my $str = '[0|0|{A=145,B=2,C=12,D=18}|!][0|0|{A=167,B=2,C=67,D=17}|.1iit][196|0|{A=244,B=6,C=67,D=12}|10:48AM][204|0|{A=9,B=201,C=61,D=11}|Calculator][66|0|{A=145,B=450,C=49,D=14}|phone]0|0|{A=145,B=2,C=12,D=18}|!0|0|{A=167,B=2,C=67,D=17}|.1iit196|0|{A=244,B=6,C=67,D=12}|10:48AM204|0|{A=9,B=201,C=61,D=11}|Calculator66|0|{A=145,B=450,C=49,D=14}|phone';

my $maxval = 0;
my $pattern;
while ( $str =~ /(\[(\d+)\|.+?\])/g) 
{
        if ( $maxval < $2 ) {   
                $maxval = $2;
                $pattern = $1;
        }
}

print "Maximum value = $maxval and the associate pattern = $pattern \n";
# In this example $maxvalue = 204
# and $pattern = [204|0|{A=9,B=201,C=61,D=11}|Calculator]

1 Comment

Sorry for the late response.. I was sick for a while. This code worked initially..but what happened was that, all the times, the maximum value was not getting returned. Sometimes the first value was getting returned. But the code of MarcOs worked correctly.. Thanks a lot anyway..

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.