exiting from a loop

I wonder if someone could help me here. I am trying to find a way of exiting from a loop but not exiting me from the script for example

#!/bin/ksh

#  *************   FUNCTIONS    ******************

function1() {      #ping test

   ping $1 2 > /dev/null
      if [ $? != 0 ] ; then
          echo "Couldn't ping $1, skipping"
          exit
      else
          echo "ping to $1 successful, continuing to function2"
      fi
}

function2() {     # now we can ping ...check the location

location=`ssh $1 'cat /etc/location'`

   if [ $location = "London" ] ; then
        loc=ldn
        echo "Location is London, passing on to function3"
   else
        echo "location is NOT London, Skipping"
        exit
    fi
}


#### main script body ####

for n in list 
do
  function1 $n
  function2 $n
  etc
  etc
done

hopefully youll get the general idea, i have a load of functions to perform for each item in my for loop, if they dont "pass" the first function, id like to not have to run through every subsequent function in the loop, id like it to quit there and move onto the next item in the for loop

I tried putting an "exit" and an "exit 0" into the fail criteria of the first function, but that quits me out of the whole script and not just that loop item,

Is there any way of doing this ?

Have you tried

exit 1

or any other non-zero value?

Replace exit by break

Thanks for the reply but whatever value of exit i give, it throws me out of the script completely

Thanks danmero, ive just tried this and it doesn't work, I'm not sure why because looking at examples on the web it seems as though it should do... I'm going to lay out my example code a little better here (because my functions are actually defined at the top of the script)

It seems the break is being ignored and moving on to the next function regardless

#!/bin/ksh

#  *************   FUNCTIONS    ******************

function1() {      #ping test

   ping $1 2 > /dev/null
      if [ $? != 0 ] ; then
          echo "Couldn't ping $1, skipping"
          break
      else
          echo "ping to $1 successful, continuing to function2"
      fi
}

function2() {     # now we can ping ...check the location

location=`ssh $1 'cat /etc/location'`

   if [ $location = "London" ] ; then
        loc=ldn
        echo "Location is London, passing on to function3"
   else
        echo "location is NOT London, Skipping"
        break
    fi
}


#### main script body ####

for n in list 
do
  function1 $n
  function2 $n
  etc
  etc
done

The break doesn't seem to be working, it will still go through all the functions sequentially for each loop item, it doesn't hit (for example) the fail condition of function1 and move on to the next loop item skipping the rest of functions for that one, it just echoes the fail message from function1, ignores the break and then moves on to function2

ok, ive done a bit of digging and it seems "continue" is the command im after to drop me out of the loop. However, the strangest thing has come to light....If i put my "continue" statement within my "if" statement within my "for" loop, then everything works as expected by throwing me out when there is a failure on the first "if" statement.... like this

#!/bin/ksh

for n in list 
do

     # what was function1
   ping $n 2 > /dev/null
      if [ $? != 0 ] ; then
          echo "Couldn't ping $n, skipping"
          continue
      else
          echo "ping to $n successful, continuing to function2"
      fi


     # what was function2
      location=`ssh $1 'cat /etc/location'`
   if [ $location = "London" ] ; then
        loc=ldn
        echo "Location is London, passing on to function3"
   else
        echo "location is NOT London, Skipping"
        continue
    fi

done

Now that is exactly what I want, apart from the fact I have had to put what were externally defined functions, physically within the for loop.

If i define them outside of the for loop and call them in, the continue statement is ignored

so the following code doesnt work

#!/bin/ksh

#  *************   FUNCTIONS    ******************

function1() {      #ping test

   ping $1 2 > /dev/null
      if [ $? != 0 ] ; then
          echo "Couldn't ping $1, skipping"
          continue
      else
          echo "ping to $1 successful, continuing to function2"
      fi
}

function2() {     # now we can ping ...check the location

location=`ssh $1 'cat /etc/location'`

   if [ $location = "London" ] ; then
        loc=ldn
        echo "Location is London, passing on to function3"
   else
        echo "location is NOT London, Skipping"
        continue
    fi
}


#### main script body ####

for n in list 
do
  function1 $n
  function2 $n
 
done

I just dont understand why it works if i embed the code, but it doesnt if I define it as a function and call it in - what is the difference, arent functions treated as embedded code when they are called in ?????

I really would prefer to keep this function based as the code is a lot tidier

Is anybody able to explain to me why this happens....im stumped :confused:

You need to do your break down on the for loop at the bottom not in the functions themselves.

I dont know what os you use but the syntax for ping doesnt work on any os that I use.

I had to change it to:

ping $1 -q -c 2

The reason I need to quit from the loop is because each function is required only upon the success of the previous function, so in this case, I dont want to waste the time and resources attempting to run function2 if function1 has failed, (there are many of these related functions which are all reliant on the success of the previous one but my example shows just two)

If function1 has failed (i.e. a ping check fails in the example given above) I do not want it to move on to function2 (which checks the contents of a file) but to instead quit out of that loop and move onto the next loop item which will start at function1 again

The idea being like a series of sequential tests with only the loop items that pass every function test getting to the very last function

I can achieve this successfully via a series of nested if's upon more nested if's or indeed if I place the if statements within the body of the "for" loop (as stated above)...but i dont really want to do that as I would prefer to get this all working with functions

hope that makes it clearer

I just updated ... guess thats what I get for not reading the original post :stuck_out_tongue:

im using solaris and the ping command works fine, im not so worried about the contents of the functions to be honest, its more a question on how the "continue" command works and the difference between it when run inside a "for" loop or when it is called via a function

ah , ok so i need to define my functions within the loop ?

ok, ive just fully tested this, if I define my functions within my "for" loop (as chatwizrd suggested) and call them (again, within the "for" loop) it still doesn't work at all !!

the only way I seem to be able to get this working is if I ditch the whole idea of functions and just put "if" statements within the "for" loop with the "continue" command used to quit the loop when a particular condition fails

It would be a real shame if this is the only way to get this working as I was really hoping for a nice tidy script possibly with my functions defined in an external functions file that I source into the script.

Any additional suggestions on how to get this working with functions would be greatly appreciated

Cheers

doing 'man ksh' yields the following:

     * break [ n ]
           Exit from the enclosed for, while,  until,  or  select
           loop,  if any.  If n is specified then break n levels.
           If n is greater than the number  of  enclosing  loops,
           the outermost enclosing loop shall be exited.

     * continue [ n ]
           Resume the next iteration of the enclosed for,  while,
           until,  or  select loop. If n is specified then resume
           at the n-th enclosed loop. If n is  greater  than  the
           number  of  enclosing  loops,  the outermost enclosing
           loop shall be used.

     * return [ n ]
           Causes a shell function or '.' script to return to the
           invoking script with the return status specified by n.
           The value will be the least significant 8 bits of  the
           specified  status.  If  n  is  omitted then the return
           status is that of the last command executed. If return
           is  invoked  while  not in a function or a '.' script,
           then it is the same as an exit.

     * exit [ n ]
           Causes the calling shell or shell script to exit  with
           the  exit status specified by n. The value will be the
           least significant 8 bits of the specified status. If n
           is  omitted  then  the exit status is that of the last
           command executed. When exit occurs  when  executing  a
           trap, the last command refers to the command that exe-
           cuted before the trap was invoked. An  EOF  will  also
           cause  the  shell to exit except for a shell which has
           the ignoreeof option (See set below) turned on.

Pick your poison - for return from shell functions use 'return'.

Thanks, I did actually see that before, however when I replace my "continue" with a "return" it completely ignores it ... I seemed to be getting a little more joy with "continue"

Is there a special way I should be using "return" ? am i doing this wrong. I thought "return" was used to pass function results back to the script, not to quit you out of an iteration of the loop ?