# Sum of even and odd numbers of odd and even lines

I would like to write a shell script program that gives the sum of even and odd numbers in a given file's odd and even lines.

I would like to use:

``````sed -n 2~2p
``````

and

``````sed -n 1~2p
``````

but I am not even sure where and how to start solving it. Could you please guide me in the right direction?

Input file example:

``````20 15 14 17
20 50 79 77
55 40 89 77
45 65 87 12
``````

Output example:

``````Odd summ: 15+17+55+89+77=253(Enough just the end of the summ)
Even summ: 20+50+12=82(Enough just the end of the summ)
``````
• Do you have to use `sed` or could you consider e.g. `awk`? Commented Nov 6, 2019 at 13:16
• Sed is not necessary. Commented Nov 6, 2019 at 13:17
• OK - can you give a short example of what your input looks like and what your output should look like? Please edit the question and add the example to the question itself - do no add it in a comment. Commented Nov 6, 2019 at 13:20

using Miller (https://github.com/johnkerl/miller) and running

``````mlr --n2c put 'for (key, value in \$*) {
if ((value % 2 ==0) && (NR % 2 ==0)) {
\$even +=value;
} elif ((value % 2 !=0) && (NR % 2 !=0)) {
\$odd +=value;
}
}
' then unsparsify then stats1 -a sum -f odd,even input.csv
``````

you will have

``````odd_sum,even_sum
253,82
``````

With `perl`:

``````perl -lne '\$odd = \$. & 1; \$sum[\$odd] += \$_ for grep {(\$_ & 1) == \$odd} /\d+/g;
END {
print "Sum of odd numbers on odd lines: " . (0+\$sum[1]);
print "Sum of even numbers on even lines: " . (0+\$sum[0]);
}' < file
``````

(here only considering sequences of decimal digits in the input, you may need to adapt if you also want to consider negative numbers or hexadecimal, octal ones...)

On your sample input, it gives:

``````Sum of odd numbers on odd lines: 253
Sum of even numbers on even lines: 82
``````

``````perl -MList::Util=sum -lne '
\$odd = \$. & 1;
push @{\$l[\$odd]}, grep {(\$_ & 1) == \$odd} /\d+/g;
END {
\$" = "+";
print "Odd sum: @{\$l[1]}=" . sum(@{\$l[1]});
print "Even sum: @{\$l[0]}=" . sum(@{\$l[0]});
}' < file
``````

Note that your `sed -n 2~2p` and `sed -n 1~2p` are GNU extensions. The standard equivalents would be respectively: `sed 'n;d'` and `sed '1d;n;d'`.

Or, since only odd (row or value) + even (value or row) = odd (test output) ...

``````awk '{
for (i=1;i<=NF;i++)
{if ((\$i+NR)%2==0) {if (\$i%2==0) {
seven+=\$i; even=even "+" \$i} else {sodd+=\$i; odd=odd "+" \$i} }
}
} END {
print "Evens:", substr(even,2,length(even)-1) "=" seven;
print "Odds:", substr(odd,2,length(odd)-1) "=" sodd;
}' file
``````

Output

``````Evens: 20+50+12=82
Odds: 15+17+55+89+77=253
``````
• This does not answer the exact question, it gives correct results for the sample data but not for the requirements stated in question. Commented Nov 6, 2019 at 20:30
• @EOhm, please Elucidate.... it is just a different logic approach for the odd/even match. If the the sum of the value and the row is even then OP wants it, after than we just have to decide whether it belongs in the odd/odd set or the even/even set. Commented Nov 6, 2019 at 20:35
• oh sorry yes You are right. I misread Your statement. (i read it as `if i+NR%2==0` which would be a different thing. So yes Your way gives correct results, thought it is a quite ugly looking way that would not scale. But well it's correct and it would not give that results if it were wrong the way I misread first. Commented Nov 6, 2019 at 21:06
• Aha, yes. In fact I made exactly that typo when I first tested the code and i fried my brain for a minute trying to figure it out. As long as it's OK as posted, then fine. OP has ideas to try out that shouldn't break too easily. Thx for keeping a watch. Commented Nov 6, 2019 at 21:48

Using the linux `dc` utility:

``````cat file |
dc -e "
[q]sq
[lO+dsO]sa
[lE+dsE]sb
[d2%1=a sz z0<o]so
[d2%0=b sz z0<e]se
[?z0=q lN1+sN lN2%1=o lN2%0=e cz0=?]s?
zddsNsEsO
l?x
[Sum of evens=]n lEp
[Sum of  odds=]n lOp
"
``````

Results:

``````Sum of evens=82
Sum of  odds=253
``````

We could convert everything to math. In most languages `var%2` would have only two posible values, either `0` or `1`. If we can then use them as numbers to multiply, we can do (for example in awk):

``````(f%2) * f
``````

would be the value of `f` (field) if that value is odd and `0` otherwise.
So, in awk, this is enough:

``````awk '{
for(f=1;f<=NF;f++){
so +=  (NR%2) *  (\$f%2) * \$f;
se += !(NR%2) * !(\$f%2) * \$f
}
}END{
print(so,se)
}
' filetotest
``````

Where `NR` is the number of the record and `f` is the number of the field.