Is there a goto statement in bash?
No, there is not; see §3.2.4 "Compound Commands" in the Bash Reference Manual for information about the control structures that do exist. In particular, note the mention of break
and continue
, which aren't as flexible as goto
, but are more flexible in Bash than in some languages, and may help you achieve what you want. (Whatever it is that you want . . .)
How to use goto statement in shell script
As others have noted, there's no goto
in bash
(or other POSIX-like shells) - other, more flexible flow-control constructs take its place.
Look for heading Compound Commands
in man bash
.
In your case, the select
command is the right choice.
Since how to use it may not be obvious, here's something to get you started:
#!/usr/bin/env bash
echo "Main Menu"
# Define the choices to present to the user, which will be
# presented line by line, prefixed by a sequential number
# (E.g., '1) copy', ...)
choices=( 'copy' 'exit' )
# Present the choices.
# The user chooses by entering the *number* before the desired choice.
select choice in "${choices[@]}"; do
# If an invalid number was chosen, $choice will be empty.
# Report an error and prompt again.
[[ -n $choice ]] || { echo "Invalid choice." >&2; continue; }
# Examine the choice.
# Note that it is the choice string itself, not its number
# that is reported in $choice.
case $choice in
copy)
echo "Copying..."
# Set flag here, or call function, ...
;;
exit)
echo "Exiting. "
exit 0
esac
# Getting here means that a valid choice was made,
# so break out of the select statement and continue below,
# if desired.
# Note that without an explicit break (or exit) statement,
# bash will continue to prompt.
break
done
Skip (goto) a piece of code in bash?
No, there isn't.
But this example doesn't need it:
read -p "WAN1 exists?: " -n 1 -r
if [[ $REPLY =~ ^[Yy]$ ]]; then
# WAN1
read -p "Enter WAN1 IP: " wan1
if [[ $wan1 =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
sed -i~ -e "s/bizip/$wan1/g" test.txt
else
echo Error
fi
fi
# WAN2_prompt
read -p "WAN2 exists?: " -n 1 -r
if [[ $REPLY =~ ^[Yy]$ ]]; then
read -p "Enter WAN2 IP: " wan2
if [[ $wan2 =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
sed -i~ -e "s/bizip/$wan2/g" test.txt
else
echo Error
fi
fi
# ...
Goto beginning of if statement?
You have to use a loop; bash
doesn't have a goto
statement.
while true; do
# set the value of INPUT here
if [ "$INPUT" = "no" ]; then
Do something
elif [ "$INPUT" = "yes" ]; then
Do something else
else
echo "Input not understood"
continue
fi
break
done
In this "infinite" loop, we use the continue
statement in the else
clause to return to the top of the loop, where we do something to get a new value of INPUT
. If we don't execute the else
clause, we hit the break
statement, which exits the loop.
how do you goto in mac shell (like a in windows .bat)?
There's actually no exact replacement. In bash
programming, you can define functions, so you might do something like
one() {
# Some stuff
two
}
two() {
# Some more stuff
one
}
Although eventually that'll run out of stack space; hopefully there's some circumstances under which you'll include code to stop the recursion. I realize this is just a straw man example, but bash
would let you use other forms of loops here which would work better; for example:
while true
do
# Some stuff
# Some more stuff
done
What could be the substitute to handle the flow control of go-to in SHELL script
Rather than trying to extend the syntax of the shell to do
start:
for ...; do
for ...; do
...
done
done
if CONDITION; then
goto start
else
SOMETHING
fi
you may do
while true; do
for ...; do
for ...; do
...
done
done
if ! CONDITION; then
SOMETHING
break
fi
done
or
while true; do
for ...; do
for ...; do
...
done
done
if ! CONDITION; then
break
fi
done
SOMETHING
UPDATE: New code in question:
start:
while true; do
for ...; do
for ...; do
if ...; then
break 99
fi
...
done
done
done
...
if CONDITION; then
SOMETHING
goto start
else
SOMETHING_ELSE
fi
for ...; do
...
done
To avoid a goto, this may be transformed into
while true; do
while true; do
for ...; do
for ...; do
if ...; then
break 99 # change to one less than
# the total depth, to not exit
# outermost loop
fi
...
done
done
done
...
if ! CONDITION; then
break
fi
SOMETHING
done
SOMETHING_ELSE
for ...; do
...
done
Something similar to goto on linux
Bourne shells like sh
and bash
don't have GOTO statements. It's considered harmful.
Instead, use structured flow control like if statements:
echo "Enter the number to divide (dividend) (enter 999 to quit):"
read numberOne
if [ "$numberOne" -ne 999 ]
then
echo "Enter the number to divide (divisor) (enter 999 to quit):"
read numberTwo
while [ "$numberOne" -ne '999' ] && [ "$numberTwo" -ne '999' ]
do
while [ "$numberTwo" -eq 0 ]
do
echo "You cannot divide by 0, please enter another number:"
read numberTwo
done
RESULT=$(echo "$numberOne/$numberTwo" | bc -l)
echo $numberOne / $numberTwo = $RESULT
echo $numberOne / $numberTwo = $RESULT >> results.txt
echo "Enter the number to divide (dividend) (enter 999 to quit):"
read numberOne
if [ "$numberOne" -ne 999 ]
then
echo "Enter the number to divide (divisor) (enter 999 to quit):"
read numberTwo
fi
done
fi
counter=1
totalCount=0
temporal=0
while [ "$counter" -lt '101' ]
do
temporal=$( expr $counter % 5)
echo $counter MOD 5 = $temporal
echo $counter MOD 5 = $temporal >> results.txt
totalCount=$(echo "$totalCount+$temporal" | bc -l)
counter=$(echo "$counter+1" | bc -l)
done
average=$(echo "$totalCount/100" | bc -l)
echo The average of all the MODs is $average >> results.txt
It may seem more awkward than one simple goto, but as you take advantage of more structured control flow, the code gets easier to read and follow:
readNumber() {
local number
read -p "$1" number
[ "$number" -ne 999 ] && echo "$number"
}
while one=$(readNumber "Enter dividend or 999 to quit: ") && \
two=$(readNumber "Enter divisor or 999 to quit: ")
do
echo "$one / $two = $(echo "$one / $two" | bc -l)" | tee results.txt
done
This keeps asking for numbers to divide, until the user enters 999 for either of them.
Related Topics
Rename All Files in a Folder With a Prefix in a Single Command
Mount Smb/Cifs Share Within a Docker Container
Argument List Too Long Error For Rm, Cp, Mv Commands
Deploying Yesod to Heroku, Can't Build Statically
How to Install Gcc 4.9.2 on Rhel 7.4
Adding a New Entry to the Path Variable in Zsh
Appending a Line to a File Only If It Does Not Already Exist
How to Redirect Output of Systemd Service to a File
Which Linux Ipc Technique to Use
How to Programmatically Disable Hardware Prefetching
How to Detect Invalid Utf8 Unicode/Binary in a Text File
Format and Then Convert Txt to CSV Using Shell Script and Awk
How to Write a Bash Script to Restart a Process If It Dies
How to Run a Shell Script At Startup
How to Recursively Find All Files in Current and Subfolders Based on Wildcard Matching
How to Join Multiple Lines of File Names into One With Custom Delimiter
How to Quickly Sum All Numbers in a File
How to Pass the Password to Su/Sudo/Ssh Without Overriding the Tty