1

I am using an if condition inside a for loop. If the if condition returns yes, then I'd like to go to the start of the for loop again. Is this possible in bash?

#!/bin/bash
for i in /apps/incoming/*.sql
do
j=$(egrep "[A-Z]{6}[ ]{1}[@abc_id]{10}[ ]{1}[=]{1}[ ]{1}[0-9]*" $i | awk '{ print $4 }')
#echo $j

#Query database

export ORACLE_HOME=/apps/uc/tmd/oracle/instantclient_11_2
export LD_LIBRARY_PATH=/apps/uc/tmd/oracle/instantclient_11_2
sqlplus=/apps/oracle/instantclient_11_2/sqlplus

tmprnt=$($sqlplus -s abcsd/sakfdj@'(DESCRIPTION =(ADDRESS_LIST =(ADDRESS = (PROTOCOL = TCP)(HOST = odsakjfldkjf)(PORT = 1111)))(CONNECT_DATA =(SERVICE_NAME = SFDDFD)(SRVR = DEDICATED)))' << EOF

SELECT name from blabla where abc_id='$j';
EOF)

if `echo ${tmprnt} | grep "${searchString1}" 1>/dev/null 2>&1`
then
  GO TO the start of FOR IN loop and run the query again. 

So if above tmprnt variable inside the IF condition matches the search string, then I'd like to run the thing again (The SQL query return "no rows selected" sometimes but it somehow returns correct results in we run again). I know there is no GO TO in bash. Please suggest a way out.

Koshur
  • 1,359

2 Answers2

3

If you want to move on to the next query, use the continue statement.

If you want to repeat the same query, use a loop. You want to repeat the query, so write a script that does that, rather than disguising your intent with a low-level construct that doesn't even exist in the language you're using.

for i in /apps/incoming/*.sql
do
  while
    j=$(…)
    …
    ! echo "${tmprnt}" | grep "${searchString1}" 1>/dev/null 2>&1
  do
    … # whatever you want to do when $tmprnt has the right format
  done
done

I corrected the conditional statement you wrote to what you probably meant — executing the output of grep as a shell snippet doesn't make sense. Also remember to put double quotes around variable and command substitutions.

Note the logic here: while the search string is not present, repeat the query.

That script would be querying the database in a tight loop, so something is missing here (hopefully code that you just omitted to keep the question simple).

1

Yes, there is a way, but you should never use it in a new script you're developing because it's just a workaround.

However, When I moved from Windows to Linux on my desktop, I had a lot of pre-existing .BAT and .CMD files to convert and I wasn't going to rewrite the logic for them, so I found a way to do a goto in bash that works because the goto function runs sed on itself to strip out any parts of the script that shouldn’t run, and then evals it all:

#!/bin/bash

# BAT / CMD goto function
function goto
{
    label=$1
    cmd=$(sed -n "/^:[[:blank:]][[:blank:]]*${label}/{:a;n;p;ba};" $0 | 
          grep -v ':$')
    eval "$cmd"
    exit
}

apt update

# Just for the heck of it: how to create a variable where to jump to:
start=${1:-"start"}
goto "$start"

: start
goto_msg="Starting..."
echo $goto_msg
# Just jump to the label:
goto "continue"

: skipped
goto_msg="This is skipped!"
echo "$goto_msg"

: continue
goto_msg="Ended..."
echo "$goto_msg"

# following doesn't jump to apt update whereas original does
goto update

and I do not feel guilty at all as Linus Torvalds famously said:

From: Linus Torvalds
Subject: Re: any chance of 2.6.0-test*?
Date: Sun, 12 Jan 2003 11:38:35 -0800 (PST)

I think goto's are fine, and they are often more readable than large amounts of indentation. That's especially true if the code flow isn't actually naturally indented (in this case it is, so I don't think using goto is in any way clearer than not, but in general goto's can be quite good for readability).

Of course, in stupid languages like Pascal, where labels cannot be descriptive, goto's can be bad. But that's not the fault of the goto, that's the braindamage of the language designer.

Original source for the code (modified to make it less error prone)
The source for the quote

Fabby
  • 5,384