LinuxQuestions.org

LinuxQuestions.org (/questions/)
-   Linux - Newbie (https://www.linuxquestions.org/questions/linux-newbie-8/)
-   -   Bash script - number testing issue (https://www.linuxquestions.org/questions/linux-newbie-8/bash-script-number-testing-issue-921279/)

ravedog 12-30-2011 04:39 PM

Bash script - number testing issue
 
Heya!

I'm working on a cgi-bin script and bumped in to an issue. I will have around 500-600 objects red with in a while statement that just echoes the name and moves along as long as there is more to read. However i would like to, after 10 entries, to break and use a new line.

In the while statement i have a var that +1 for every cycle in the loop, but what would be a good way to match all tens (both 10,20,30.....220,230,240) and break it off?

It has crossed my mind to test the var and see if it ends with a "0" and in that case break for new line. But how?

I pasted in the code i'm stuck with right now below, which obviously don't work :)


Code:

wcount=0
while read line
 do
  echo '<td><font size="1" face="arial">'$line"</font></td>"
  wcount=$(expr $wcount + 1)
      if [ $wcount -eq *0 ]; then
        echo "</tr><tr>"
      fi
 done < $list

big thanks in advance!

/R

Roken 12-30-2011 04:56 PM

Why not just increment wcount by 10 instead of 1?

Code:

wcount=$(expr $wcount + 10)
Scratch that - just realised :)

ravedog 12-30-2011 05:03 PM

Hehe :) Thanks for quick reply though!

Roken 12-30-2011 05:41 PM

OK - been playing. This will only echo every 10th number. Modify to suit your needs :)

(it only counts to 100 then exits, just for testing. You can remove the while statement)
Code:

#!/bin/bash

wcount=0
testcount=$wcount
while [ $wcount -lt 100 ];
do
  wcount=$(expr $wcount + 1)
  test=$(expr $wcount / 10)
  if [ `echo $test | sed 's/^.*\.//'` -gt $testcount  ]; then
    echo $wcount
    testcount=$(expr $testcount + 1)
  fi
done

Note: You can substitute "/ 10" in line 8 for "/ whatever number" to change the tested increment.

ravedog 12-30-2011 05:52 PM

Hey Roken!

Thanks for your answer! I tried it and just as you said, every 10 was echoed :)

This is however, a rather advanced solution to the problem though. I would have bet that there was a good way to do this from within the if test itself with "built ins". Something along the way of:

Code:

if [ $wcount -eq *?0 ]; then
echo "This ends with 0 and has at least one number in front of it"
fi

But I'm not at all sure of that and ill definitely look in to modify your solution to do it if no such solution exists.

Thanks mate!

/R

Cedrik 12-30-2011 05:59 PM

Code:

wcount=0
while read line
 do
  echo '<td><font size="1" face="arial">'$line"</font></td>"
  let wcount++
      if [[ "$wcount" = *0 ]]; then
        echo "</tr><tr>"
      fi
 done < $list


ravedog 12-30-2011 06:02 PM

Worked like a charm, thanks to both of you for the solutions!

/R

Roken 12-30-2011 06:05 PM

To test for every ten then Cedriks solution is cleaner. If you want to change the frequency (e.g., every 4, every 7, every 9, every 21 etc) then mine is more portable. However, I just found that bash doesn't do floating point, so it can be simplified somewhat (you need to use bc for floating point math).

Code:

#!/bin/bash

wcount=0
testcount=$wcount
while [ $wcount -lt 100 ];
do
  wcount=$(expr $wcount + 1)
  if [ $(expr $wcount / 9) -gt $testcount  ]; then
    echo $wcount
    testcount=$(expr $testcount + 1)
  fi
done

(this one does every 9th :) ) EDIT: simpler still

ravedog 12-30-2011 06:09 PM

@ Roken: Ah ok i see, well in this case it will only break to a new row when 10 names (10 cols) from the list has filled the width of the html table that it resides in. So for this case, the simplest possible will do fine.

However i love learning new stuff so ill bookmark this for future refs. :)

Again thanks for your efforts!

br,

/R

David the H. 12-31-2011 10:44 AM

Why are using expr here, when there is absolutely no need for it? The shell can do integer math, and you have to use bc or awk for floating point anyway.

To increment an integer variable by one, you can simply use (( i++ )), and by other factors, use (( i+=2 )), etc. (There are many ways you can use arithmetic in the shell...see here for more.)

Also, numeric tests in bash should be done with the same ((..)) arithmetic evaluation field, and string tests should be done with the new [[..]] test. Don't use the old [..] test unless you need POSIX-based compatiblity.


Anyway, it looks like you need to learn about the "%" (modulo) arithmetic operator. It outputs the remainder after a division operation, for example, "6 % 4 --> 2" and "6 % 3 --> 0". Whenever you get 0, you know you have an even multiple of the divisor.

Code:

while read line; do

    (( wcount++ ))

    if (( wcount % 10 == 0 )); then
          echo "$wcount"
    fi

done <$list

Here are three more ways to work with incremental values in bash:

1) A c-style for loop.

2) brace expansion

3) The seq command

Roken 12-31-2011 11:13 AM

Quote:

Originally Posted by David the H. (Post 4562592)
Anyway, it looks like you need to learn about the "%" (modulo) arithmetic operator. It outputs the remainder after a division operation, for example, "6 % 4 --> 2" and "6 % 3 --> 0". Whenever you get 0, you know you have an even multiple of the divisor.

Good call. I knew about this, of course, and completely forgot it. Thanks for the reminder :)


All times are GMT -5. The time now is 01:45 AM.