Reputation: 17930
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
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
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
Reputation: 15493
Timtowtdi (as usual).
perl -nE '$s+=$1, ++$n if /x_y=(\d+)/; END { say "avg:", $s/$n }' data.txt
Upvotes: 6
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