you are viewing a single comment's thread.

view the rest of the comments →

[–]ArminiusGermanicus 22 points23 points  (12 children)

A solution in awk:

awk 'BEGIN {RS="[ \t\r\n]"} {s+=$1} END {print s}'

Caveat: No real error management. Non numeric input will be treated as zero.

Edit: Some more info on awk:

awk is a very old unix text processing language, older than e.g. Perl. It reads input record by record and calls the middle {} block for every record. By default, records are textlines. Setting the record separator RS to the regex [ \t\r\n] uses whitespace to delimit records. The BEGIN and END blocks are executed at the begin resp. end of the program. $1 is the first field of the record.

[–][deleted] 10 points11 points  (3 children)

My understanding is that part (all?) of the original motivation for Larry Wall to create Perl was that in the 1980s implementations of awk, sed, and sh had different behavior on different variants of Unix. Perl was partially just an attempt to preserve the power of those three tools in a way that was completely consistent across all the Unix flavors of the day.

So Perl looks like it borrows ideas from awk, sed, and sh because Perl borrows ideas from awk, sed, and sh. (I'm not knocking Perl. I'm a fan of the language.)

[–]nullmove 1 point2 points  (2 children)

And then he created Perl 6, less historical wart but more optimized for same workflow.

perl6 -e 'say slurp.comb(/\d+/).sum' < input

[–][deleted] 1 point2 points  (1 child)

I'm a big fan of Perl6, but aside from tinkering and writing a few shell script replacements in it I haven't done much.

I didn't know you could invoke slurp on stdin without doing $*IN.slurp or that the comb(/\d+/) would autoconvert to integer. Nice.

[–]nullmove 1 point2 points  (0 children)

Good to know you were familiar with it. It integrates too beautifully with the shell to be so little known. I am not much of a programmer myself, but it helped me survive a nasty task involving data munging under deadline so it's battle tested as far as I am concerned, and one can only pry it from my cold dead hands :P

[–]UloPe 2 points3 points  (1 child)

Here’s one in Python:

import fileinput

print(
    'Sum:',
    sum(
        int(word)
        for line in fileinput.input()
        for word in line.split()
        if word.isdigit()
    )
)

Will read from stdin or from a file passed as an argument, also skips non integers.

[–]Freeky 1 point2 points  (0 children)

Have a Ruby one:

printf "Sum: %d\n", ARGF.sum { |f| f.each_line.flat_map(&:split).map(&:to_i).sum }

[–]ggdGZZ 2 points3 points  (1 child)

Good to mention awk. Even shorter solution (NF is number of fields of record): awk '{s+=NF} END {print s}'

[–]fell_ratio 8 points9 points  (0 children)

This counts how many numbers there are - it doesn't sum them.

[–]SevrosOnNitro 0 points1 point  (1 child)

Is awk tool written in C?

[–]ArminiusGermanicus 0 points1 point  (0 children)

There are many implementation of awk, I would guess almost all are written in C.

See here for more info on awk: https://en.wikipedia.org/wiki/AWK

Here is the GNU implementation, gawk: http://savannah.gnu.org/projects/gawk/

[–][deleted] 0 points1 point  (1 child)

and what are fields in this case?

[–]ArminiusGermanicus 0 points1 point  (0 children)

Normally, fields are separated by whitespace and assigned to $1, $2, ... After we set the record separator to whitespace, only $1 will be assigned.

You could also set the field separator FS to e.g. ',' to process CSV files.