Help with a shell script?

Discussion in 'Mac Programming' started by msjones, Apr 15, 2011.

  1. macrumors 6502

    msjones

    Joined:
    Oct 18, 2007
    Location:
    Nottinghamshire, UK
    #1
    Evening all,

    I am having a little fun with some shell scripting but I am stuck creating a loop. Hopefully someone can help. Here is my script:

    Code:
    #!/bin/bash
    
    FORTUNE=`fortune -i`
    COUNT=`echo $FORTUNE | wc -m`
    
    if [ $COUNT -lt 140 ]
     then
      while true; do
      echo "$FORTUNE" && exit
     done
    fi
    As you can see if $FORTUNE is less than 140 characters it will echo the text and then close. If $FORTUNE is greater than 140 it will just close. What I want it to do is if its greater than 140 to re-run again until its less than 140, echo and then exit.

    Hope this makes sense?
     
  2. macrumors 603

    Joined:
    Aug 9, 2009
    #2
    According to that description, the if must be inside a loop, not outside it. So structurally you need this:
    Code:
    while ..
      ..
      if ..
        ...
      fi
      ..
    done
    
    but your posted code has this:
    Code:
    if ..
      while ..
        ..
      done
    fi
    
     
  3. thread starter macrumors 6502

    msjones

    Joined:
    Oct 18, 2007
    Location:
    Nottinghamshire, UK
    #3
    OK So ive changed to this:

    Code:
    #!/bin/bash
    
    FORTUNE=`fortune -i`
    COUNT=`echo $FORTUNE | wc -m`
    
    while true; do
     if [ $COUNT -lt 140 ]
      then
       echo "$FORTUNE" && exit
     fi
    done
    
    This will post if $FORTUNE is less than 140 but if its greater than 140 it just hangs?
     
  4. macrumors member

    Joined:
    Jan 29, 2009
    Location:
    Canada
    #4
    Thats because you have no exit condition if the count is not less than 140...you have an infinite loop.
     
  5. msjones, Apr 15, 2011
    Last edited: Apr 15, 2011

    thread starter macrumors 6502

    msjones

    Joined:
    Oct 18, 2007
    Location:
    Nottinghamshire, UK
    #5
    This is where I am at currently:

    Code:
    #!/bin/bash
    
    FORTUNE=`fortune -i`
    COUNT=`echo $FORTUNE | wc -m`
    
    while [ $COUNT -lt 140 ]
     do
       echo "$FORTUNE"
       exit 0
    done
    
    This works fine, but still can't get it to loop if $COUNT is greater than 140. I have scoured google and I can only find that when a while loop hits its false it will exit?
     
  6. macrumors 6502a

    itickings

    Joined:
    Apr 14, 2007
    #6
    Yeah, thats the point. You use a while loop to do something as many times it takes until the condition is met.

    If you think about it, what is it that you want to repeat and update?
    Put that inside the loop. (You may need to put it before the loop as well to have a value to start with to get into the loop)

    What do you only want to do one time?
    Put that outside the loop.
     
  7. macrumors 603

    Joined:
    Aug 9, 2009
    #7
    You won't find the answer by googling. You have a structural logic problem, not a shell syntax problem.

    In your loop, does the value of FORTUNE ever change? Does the value of COUNT ever change?

    If the values don't change within the loop, then the conditions that cause the loop to loop won't change. A loop with unchanging loop conditions is the definition of an infinite loop. You effectively have:
    Code:
    while [ unchanging condition ]
    do
      echo unchanging value
      exit 0 ## always executes, because && conditional removed
    done
    
    So where are the statements that cause FORTUNE and COUNT to change? Where should they be placed if you want them to occur within the loop?
     
  8. thread starter macrumors 6502

    msjones

    Joined:
    Oct 18, 2007
    Location:
    Nottinghamshire, UK
    #8
    Yeah the value changes. Fortune is a Linux command line application that gives a fortune every time it's run. I want to post this output to twitter and as you may know twitter only takes 140 characters.

    So when my script runs if the fortune is less than 140 it will post. If it's greater than 140 I want it to keep running the command till a fortune less than 140 is given then post it.

    For the time being I am just echoing the fortune, eventually I will be using the twidge application to post to twitter, which I already have set up and working, I'll just ammed the script once I get the loop sorted.
     
  9. macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #9
    So you need to actually run fortune inside the loop. The loop would run fortune until it gets an appropriate one. Then after the loop, you output it.
     
  10. macrumors 68020

    pilotError

    Joined:
    Apr 12, 2006
    Location:
    Long Island
    #10
    What is the exit condition?

    Code:
    #!/bin/bash 
             COUNTER=0
             while [  $COUNTER -lt 10 ]; do
                 echo The counter is $COUNTER
                 let COUNTER=COUNTER+1 
    
                 ** Your Code Here **
             done
    
    If I remember correctly, fortune just does a random line search on a text file in the system somewhere. If you run it in a loop, it will run forever, and you'll be tweeting the same crap over and over. The Twitterverse will hunt you down and beat you! LOL
     
  11. macrumors 603

    Joined:
    Aug 9, 2009
    #11
    I don't think you're walking through your code. You should sit down with a paper and pencil and walk through it while pretending to be the computer.

    I do not mean "Imagine walking through it". I mean actually walk through it one line at a time, and actually write out what happens at each command line step. Then answer this question: Within the loop, when and where does the value of FORTUNE or COUNT change? If you can't find that place, then the problem and solution should be obvious.

    In olden days this was called "bench-checking your work".
     
  12. macrumors 6502

    Joined:
    Apr 29, 2010
    #12
    What happens when you replace "-lt" with "-le"?
     
  13. msjones, Apr 16, 2011
    Last edited by a moderator: Apr 16, 2011

    thread starter macrumors 6502

    msjones

    Joined:
    Oct 18, 2007
    Location:
    Nottinghamshire, UK
    #13
    Thanks for all the responses guys, will be having another crack at this later on today. Will post back when I've sorted it :)

    Finally got it working with an infinite loop:

    Code:
    FORTUNE=`fortune`
    
    while true; do
        FORTUNE=`fortune`
        if [ "${FORTUNE:140}" == "" ]; then
            break
        fi
    done
    
    echo $FORTUNE
    
    Thanks for all the input :)
     
  14. macrumors 6502

    Joined:
    Apr 29, 2010
    #14
    Can the if-condition become the loop condition, so you won't need to break out of an infinite loop? Can you replace "while true; do" with "while [ "${FORTUNE:140}" == "" ];" or with something like it? I usually don't write bash scripts, since I'm more familiar with tcsh.

    Bill
     
  15. thread starter macrumors 6502

    msjones

    Joined:
    Oct 18, 2007
    Location:
    Nottinghamshire, UK
    #15
    I tried this originally and the script will not run, it just returns a blank.
     
  16. chown33, Apr 16, 2011
    Last edited: Apr 16, 2011

    macrumors 603

    Joined:
    Aug 9, 2009
    #16
    Why?

    Efficiency? It's a shell-script, for bog's sake.

    Besides, you'd have to reverse the conditional to !=, or use the until keyword in bash.

    EDIT:
    Doing a little research on 'fortune' programs, it appears the most common implementations have command-line options for the length of the fortune chosen. The options -s -n 140 appear to limit fortune's output to only those epigrams shorter than 140 chars.

    So as an exercise in learning shell scripting, this may have been useful. As an exercise in reading man pages before embarking on projects, maybe not so much.
     

Share This Page