Home > front end >  Compare number from a txt file with an number in bash script
Compare number from a txt file with an number in bash script

Time:07-27

I am trying to read text file which contain numbers line by line in

test.txt

10.5
0.52
78.5
29.8
45
13
21.45
0.02
0.99
1.00

I want to read the number one by one and compare it with 30. I am not getting how can I do it.

I tried this but its not working.

#!/bin/bash

file=~/test.txt

while IFS= read -r line
do
    echo $line
        if [[ "$line > 30" | bc) -eq "1" ]]; then
            echo Greater
        else
            echo Smaller
        fi
done < $file

Please note: I am new to programing

CodePudding user response:

A shell is a tool to create/destroy files and processes and sequence calls to other tools. The mandatory POSIX tool that shell has available to manipulate text (as you're trying to do) is awk. So the right way to do what you're trying to do in a shell is to just call awk and let awk do the rest:

$ awk '{print $1, ($1 > 30 ? "Greater" : "Smaller")}' test.txt
10.5 Smaller
0.52 Smaller
78.5 Greater
29.8 Smaller
45 Greater
13 Smaller
21.45 Smaller
0.02 Smaller
0.99 Smaller
1.00 Smaller

I just copied the logic from your code but of course "Smaller" should really be "Smaller or equal to".

Read why-is-using-a-shell-loop-to-process-text-considered-bad-practice to learn the very important lesson of why not to write shell loops to manipulate text.

CodePudding user response:

This line:

        if [[ "$line > 30" | bc) -eq "1" ]]; then

should be:

        if [[ $(echo "$line > 30" | bc) -eq "1" ]]; then

CodePudding user response:

Using a pipeline of unix tools will probably be a lot faster (particularly as this only calls bc once)

cmp=30

paste test.txt <(sed "s/\$/ > $cmp/" test.txt | bc) \
| awk '{$2 = ($2 == 0) ? "Smaller" : "Greater"; print}' \
| column -t
10.5   Smaller
0.52   Smaller
78.5   Greater
29.8   Smaller
45     Greater
13     Smaller
21.45  Smaller
0.02   Smaller
0.99   Smaller
1.00   Smaller

You can feed bc multiple expressions, and it will return with one answer per line.


If you use another shell (zsh or ksh) you don't need any external tools:

while IFS= read -r num; do
    printf '%s\t' "$num"
    (( num > 30 )) && print Greater || print Smaller
done < test.txt

CodePudding user response:

It's always safer to add unary " " in front of variables and fields to ensure the comparison must be done numerically, leaving nothing to chance or implementation peculiarities

( it's same as x 0 with less verbosity; x is a syntax error due to extra space) :

{m,g}awk '$  NF =  __ <  $_ ? " >" : "<="' OFS='\t' __=30
10.5   <=
0.52   <=
78.5    >
29.8   <=
45      >
13     <=
21.45  <=
0.02   <=
0.99   <=
1.00   <=
  • Related