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 <=