Home > Back-end >  Read numbers from a file - 3 numbers per line - and add the results in BASH
Read numbers from a file - 3 numbers per line - and add the results in BASH

Time:10-27

So we have a test file that has a 3 digit number per line, several hundred lines of in the file.

I need to find a way to read from the file the number (or 3 digits that make up the number), add them together, and then determine if the resulting sum is odd or even. My current script is reading each line as a whole number, and I am missing the part where I am able to sum the digits...

while read number
do

echo $number
if [ $((number % 2)) -eq 0 ]; then 
  echo even
else
  echo odd
fi
done < input.txt

CodePudding user response:

Setup:

$ cat input.txt
123
456
789

Assuming the results need to be used in follow-on operations then one bash idea:

while read -r in
do
    sum=$(( ${in:0:1}   ${in:1:1}   ${in:2:1} ))
    result="odd"
    [[ $((sum%2)) -eq 0 ]] && result="even"
    echo "${in} : ${sum} : ${result}"
done < input.txt

This generates:

123 : 6 : even
456 : 15 : odd
789 : 24 : even

If the sole purpose is to generate the even/odd flag, and performance is an objective, you'll want to look at something other than bash, eg:

awk '
{ sum=0
  for (i=1;i<=length($1);i  )
      sum =substr($1,i,1)
  result=(sum%2 == 0 ? "even" : "odd")
  printf "%s : %s : %s\n",$1,sum,result
}
' input.txt

This generates:

123 : 6 : even
456 : 15 : odd
789 : 24 : even

CodePudding user response:

Something like this maybe.

#!/usr/bin/env bash

while IFS= read -r numbers; do
   [[ $numbers =~ ^([[:digit:]]{1})([[:digit:]]{1})([[:digit:]]{1})$ ]] &&  
   arr=("${BASH_REMATCH[1]}" "${BASH_REMATCH[2]}" "${BASH_REMATCH[3]}")
   sum=$(IFS= ; printf '%s' "${arr[*]}")
   if (( $((sum)) % 2 == 0)); then
     printf '%s is %d %% 2 = 0 is even\n' "$sum" "$((sum))"
   else
     printf '%s is %d %% 2 = 0 is odd\n' "$sum" "$((sum))"
   fi
done < file.txt

several hundred lines of in the file.

Bash is not the tool for this, It can be done with the shell but it will be very slow, and memory intensive, Use something like awk or perl or ...

CodePudding user response:

Simply replace

$((number % 2))

with

$(( (number/100   number/10   number) % 2))

in your code. Assuming number consists of three decimal digits, number/100 extracts the most significant digit, number/10 extracts the digit in the middle, and number extracts the least significant digit. Note that shell arithmetic is integer only, and the operators / and % have equal precedence and are left-associative.

  •  Tags:  
  • bash
  • Related