AMM
AMM

Reputation: 17930

need perl one liner to get a specific content out of the line and possibly average it

I have a file which had many lines which containts "x_y=XXXX" where XXXX can be a number from 0 to some N.

Now, a) I would like to get only the XXXX part of the line in every such line. b) I would like to get the average

Possibly both of these in one liners.

I am trying out sometihng like

cat filename.txt | grep x_y | (this need to be filled)

I am not sure what to file In the past I have used commands like

perl -pi -e 's/x_y/m_n/g' 

to replace all the instances of x_y. But now, I would like to match for x_y=XXXX and get the XXXX out and then possibly average it out for the entire file.

Any help on this will be greatly appreciated. I am fairly new to perl and regexes.

Upvotes: 3

Views: 188

Answers (4)

TLP
TLP

Reputation: 67900

As a one-liner, split up with comments.

perl -nlwe '
    push @a, /x_y=(\d+)/g          # push all matches onto an array
    }{                             # eskimo-operator, is evaluated last
    $sum += $_ for @a;             # get the sum
    print "Average: ", $sum / @a;  # divide by the size of the array
' input.txt

Will extract multiple matches on a line, if they exist.

Paste version:

perl -nlwe 'push @a, /x_y=(\d+)/g }{ $sum += $_ for @a; print "Average: ", $sum / @a;' input.txt

Upvotes: 0

Fredrik Pihl
Fredrik Pihl

Reputation: 45672

Using awk:

/^[^_]+_[^=]+=[0-9]+$/ {sum=sum+$2; cnt++}
END {
    print "sum:", sum, "items:", cnt, "avg:", sum/cnt
}

$ awk -F= -f cnt.awk data.txt
sum: 55 items: 10 avg: 5.5

Pure bash-solution:

#!/bin/bash

while IFS='=' read str num
do
    if [[ $str == *_* ]]
    then
        sum=$((sum + num))
        cnt=$((cnt + 1))
    fi

done < data.txt

echo "scale=4; $sum/$cnt" | bc ;exit

Output:

$ ./cnt.sh 
5.5000

Upvotes: 3

bobbogo
bobbogo

Reputation: 15493

Timtowtdi (as usual).

perl -nE '$s+=$1, ++$n if /x_y=(\d+)/; END { say "avg:", $s/$n }' data.txt

Upvotes: 6

Stefan Majewsky
Stefan Majewsky

Reputation: 5555

The following should do:

... | grep 'x_y=' | perl -ne '$x += (split /=/, $_)[1]; $y++ }{ print $x/$y, "\n"'

The }{ is colloquially referred to as eskimo operator and works because of the code which -n places around the -e (see perldoc perlrun).

Upvotes: 3

Related Questions