# Usage: some_app | sumFloat
# Example: printf -- "-3\n0.14" | sumFloat
# Result: -2.860000
-# Version: 0.0.1
+# Version: 0.0.2
# Depends: bc 1.07.1
yell() { echo "$0: $*" >&2; } # print script path and all args to stderr
-die() { yell "$*"; exit 111; } # same as yell() but non-zero exit status
+dief() { yell "$*"; return 111; } # same as yell() but non-zero return status
must() { "$@" || die "cannot $*"; } # runs args as command, reports args if command fails
sum_float() {
+ # Desc: Sums newline-delimited floats received on stdin
+ # Usage: some_app | sum_float
+ # Depends: bc 1.07.1, paste (GNU coreutils)
+
# Check dependencies
- if ! command -v bc 1>/dev/random 2>&1; then die "FATAL:Missing:bc"; fi;
+ command -v bc 1>/dev/random 2>&1 || { dief "FATAL:Missing:bc"; };
+ [[ ! -t 0 ]] || { dief "FATAL:No stdin detected."; };
- # Store stdin
- if [[ -p /dev/stdin ]]; then
- input_stdin="$(cat -)" || {
- die "FATAL:Error reading stdin."; };
- else
- die "FATAL:No stdin detected.";
- fi;
-
# Process lines
- local sum="0.0";
- local re;
+ local line re; local -a nums=();
re='^[+-]?([0-9]+([.][0-9]*)?|[.][0-9]+)$';
- if [[ -n $input_stdin ]]; then
- while read -r line; do
- if ! [[ "$line" =~ $re ]]; then die "FATAL:Not a float:${line}"; fi;
- sum="$(printf -- "%f + %f\n" "$sum" "$line" | bc -l;)";
- done < <(printf "%s\n" "$input_stdin") || {
- die "FATAL:Error parsing stdin."; };
- fi;
+ while IFS= read -r line; do
+ [[ -z $line ]] && continue;
+ [[ $line =~ $re ]] || { dief "FATAL:Not a float:${line}"; };
+ nums+=("$line");
+ done;
- # Print result
- printf "%f\n" "$sum";
-}; # sum stdin floats
+ # Print output
+ if (( ${#nums[@]} == 0 )); then printf '0.000000\n'; return 0; fi;
+ LC_ALL=C printf '%.6f\n' "$(printf '%s\n' "${nums[@]}" | paste -sd+ - | bc -l)";
+} # sum stdin floats
+# Author: Steven Baltakatei Sandoval
+# License: GPLv3+