Bash script ing: find the minimum value in the script

I am writing a script that finds the minimum value in a string. The line is passed to me with cat <file> , and then I parse every number inside that line. A string contains only a set of numbers separated by an interval.

This is the code:

 echo $FREQUENCIES for freq in $FREQUENCIES do echo "Freq: $freq" if [ -z "$MINFREQ" ] then MINFREQ=$freq echo "Assigning MINFREQ for the first time with $freq" elif [ $MINFREQ -gt $freq ] then MINFREQ=$freq echo "Replacing MINFREQ with $freq" fi done 

Here is the result I get:

 800000 700000 600000 550000 500000 250000 125000 Freq: 800000 Assigning MINFREQ for the first time with 800000 Freq: 700000 Replacing MINFREQ with 700000 Freq: 600000 Replacing MINFREQ with 600000 Freq: 550000 Replacing MINFREQ with 550000 Freq: 500000 Replacing MINFREQ with 500000 Freq: 250000 Replacing MINFREQ with 250000 Freq: 125000 Replacing MINFREQ with 125000 Freq: : integer expression expected 

The problem is that the last line for some reason is empty or contains spaces (I'm not sure why). I tried to check if the variable was set: if [-n "$ freq"], but this test does not seem to work fine, it still passes the if statement for the last line.

Can someone please help me figure out why the last time the loop is executed, $ freq is set to empty or whitespace and how to avoid this?

EDIT:

 using od -c feeded with echo "<<$freq>>" 0000000 < < 8 0 0 0 0 0 > > \n 0000013 0000000 < < 7 0 0 0 0 0 > > \n 0000013 0000000 < < 6 0 0 0 0 0 > > \n 0000013 0000000 < < 5 5 0 0 0 0 > > \n 0000013 0000000 < < 5 0 0 0 0 0 > > \n 0000013 0000000 < < 2 5 0 0 0 0 > > \n 0000013 0000000 < < 1 2 5 0 0 0 > > \n 0000013 0000000 < < \r > > \n 0000006 

There seems to be an extra \ r (from the file).

Thank you very much!

+4
source share
5 answers

If you only work with integer values, you can check your string with regex:

 elif [[ $freq =~ ^[0-9]+$ && $MINFREQ -gt $freq ]] 
+2
source

For the bug problem: can you have extra free space in $FREQUENCIES ?

Another solution with awk

 echo $FREQUENCIES | awk '{min=$1;for (i=1;i++;i<=NF) {if ( $i<min ) { min=$i } } ; print min }' 

If this is a really long variable, you can go with:

 echo $FREQUENCIES | awk -v RS=" " 'NR==1 {min=$0} {if ( $0<min ) { min=$0 } } END {print min }' 

(He sets the record separator to a space, then in the very first record sets the value of min to a value, then for each record check to see if it is less than min and finally prints it.

NTN

0
source

If you use bash, you have arithmetic expressions and the value "if unset: use value and assign":

 #!/bin/bash for freq in " $@ "; do (( minfreq = freq < ${minfreq:=freq} ? freq : minfreq )) done echo $minfreq 

using:

 ./script 800000 700000 600000 550000 500000 250000 125000 
0
source

Data: 10, 10.2, -3, 3.8, 3.4, 12

Minimum: echo -e "10 \ n10.2 \ n-3 \ n3.8 \ n3.4 \ n12" | sort -n | head -1
Output: -3

Maximum: echo -e "10 \ n10.2 \ n-3 \ n3.8 \ n3.4 \ n12" | sort -nr | head -1
Output: 12


How?:
1. Printing line by line
2. Sorting numbers (Reverse to get maximum)
3. Type the first line alone.
Plain!

This may not be a good method. But easy for students. I'm sure.

0
source
 echo $FREQUENCIES | awk '{for (;NF-1;NF--) if ($1>$NF) $1=$NF} 1' 
  • compare the first and last field
  • set the first field to the smaller of the two
  • delete last field
  • as soon as one field remains, print

Example

0
source

Source: https://habr.com/ru/post/1382380/


All Articles