Is there a "goto" statement in bash ? I know It is considered bad practice, but I need specifically "goto".
相关问题
- How to get the return code of a shell script in lu
- Is shmid returned by shmget() unique across proces
- how to get running process information in java?
- JQ: Select when attribute value exists in a bash a
- Invoking Mirth Connect CLI with Powershell script
I found out a way to do this using functions.
Say, for example, you have 3 choices:
A
,B
, andC
.A
andB
execute a command, butC
gives you more info and takes you to the original prompt again. This can be done using functions.Note that since the line containg
function demoFunction
is just setting up the function, you need to calldemoFunction
after that script so the function will actually run.You can easily adapt this by writing multiple other functions and calling them if you need to "
GOTO
" another place in your shell script.There is no
goto
in bash.Here is some dirty workaround using
trap
which jumps only backwards:)Output:
This shouldn't be used in that way, but only for educational purposes. Here is why this works:
trap
is using exception handling to achieve the change in code flow. In this case thetrap
is catching anything that causes the script to EXIT. The commandgoto
doesn't exist, and hence throws an error, which would ordinarily exit the script. This error is being caught withtrap
, and the2>/dev/null
hides the error message that would ordinarily be displayed.This implementation of goto is obviously not reliable, since any non-existent command (or any other error, for that manner), would execute the same trap command. In particular, you cannot choose which label to go-to.
Basically in real scenario you don't need any goto statements, they're redundant as random calls to different places only make your code difficult to understand.
If your code is invoked many times, then consider to use loop and changing its workflow to use
continue
andbreak
.If your code repeats it-self, consider writing the function and calling it as many times as you want.
If your code needs to jump into specific section based on the variable value, then consider using
case
statement.If you can separate your long code into smaller pieces, consider moving it into separate files and call them from the parent script.
This is a small correction of the Judy Schmidt script put up by Hubbbitus.
Putting non-escaped labels in the script was problematic on the machine and caused it to crash. This was easy enough to resolve by adding # to escape the labels. Thanks to Alexej Magura and access_granted for their suggestions.
You can use
case
in bash to simulate a goto:produces:
If you're testing/debugging a bash script, and simply want to skip forwards past one or more sections of code, here is a very simple way to do it that is also very easy to find and remove later (unlike most of the methods described above).
To put your script back to normal, just delete any lines with
GOTO
.We can also prettify this solution, by adding a
goto
command as an alias:Aliases don't usually work in bash scripts, so we need the
shopt
command to fix that.If you want to be able to enable/disable your
goto
's, we need a little bit more:Then you can do
export DEBUG=TRUE
before running the script.The labels are comments, so won't cause syntax errors if disable our
goto
's (by settinggoto
to the ':
' no-op), but this means we need to quote them in ourgoto
statements.Whenever using any kind of
goto
solution, you need to be careful that the code you're jumping past doesn't set any variables that you rely on later - you may need to move those definitions to the top of your script, or just above one of yourgoto
statements.If you are using it to skip part of a large script for debugging (see Karl Nicoll's comment), then if false could be a good option (not sure if "false" is always available, for me it is in /bin/false):
The difficulty comes in when it's time to rip out your debugging code. The "if false" construct is pretty straightforward and memorable, but how do you find the matching fi? If your editor allows you to block indent, you could indent the skipped block (then you'll want to put it back when you're done). Or a comment on the fi line, but it would have to be something you'll remember, which I suspect will be very programmer-dependent.