A dash to GOTO or a dash from GOTO, that is the question

Well, guys I saw a question about GOTO for Python.

So this gave me the inspiration to attempt a GOTO function for ' dash ', ( bash and ksh too).

Machine: MBP OSX 10.14.3, default bash terminal, calling ' #!/usr/local/bin/dash '...

This is purely a fun project to see if it is possible in PURE shell scripting, and so it is...

I now consider myself competent at UNIX shell scripting...

Enjoy ripping it apart:

#!/usr/local/bin/dash
# goto_demo.sh

# goto ': some_label:'
goto()
{
    line_number=1
    start_line=1
    while IFS='' read -r line
    do
        if [ "${line}" = "${1}" ]
        then
            : > /tmp/goto.tmp
            start_line=${line_number}
        fi
        if [ ${line_number} -ge ${start_line} ]
        then
            echo "${line}" >> /tmp/goto.tmp
        fi
        line_number=$(( line_number + 1 ))
    done
    . /tmp/goto.tmp
} < ${0}

goto ': second:'
echo 'This will not be printed!'
: first:
echo '**************************************'
echo 'You are at first label!'
# cat /tmp/goto.tmp
echo '**************************************'
goto ': third:'
echo 'This will not be printed either!'
: second:
echo '**************************************'
echo 'You are at the second label!'
# cat /tmp/goto.tmp
echo '**************************************'
goto ': first:'
echo 'And finally, this will not be printed either!'
: third:
echo '**************************************'
echo 'You are at the third label!'
echo '######## cat /tmp/goto.tmp... ########'
cat /tmp/goto.tmp
echo '###### END cat /tmp/goto.tmp... ######'
echo '**************************************'
: end:
echo 'Exiting...'
echo '**************************************'
exit

Results using above:

Last login: Wed Sep 18 15:55:17 on ttys000
AMIGA:amiga~> cd Desktop/Code/Shell
AMIGA:amiga~/Desktop/Code/Shell> ./goto_demo.sh
**************************************
You are at the second label!
**************************************
**************************************
You are at first label!
**************************************
**************************************
You are at the third label!
######## cat /tmp/goto.tmp... ########
: third:
echo '**************************************'
echo 'You are at the third label!'
echo '######## cat /tmp/goto.tmp... ########'
cat /tmp/goto.tmp
echo '###### END cat /tmp/goto.tmp... ######'
echo '**************************************'
: end:
echo 'Exiting...'
echo '**************************************'
exit
###### END cat /tmp/goto.tmp... ######
**************************************
Exiting...
**************************************
AMIGA:amiga~/Desktop/Code/Shell> _

EDIT:
Tested on current Linux Mint 19, using the shebang #!/bin/sh and working as per the image.

4 Likes

Isn't line_number always equal to or greater than start_line?
It works because the output file is truncated at the right moment.

I would rather go for

goto()
{
    line_copy=
    while IFS='' read -r line
    do
        [ "$line" = "$1" ] && line_copy=1
        [ -n "$line_copy" ] && echo "$line"
    done < "$0" > /tmp/goto.tmp
    . /tmp/goto.tmp
}

Eventually swap the two lines in the loop, to omit the first line (then you do not need to prefix the lable with a nop).

Of course this is a hack. A function puts something on the "return" stack...

2 Likes

I will replace my version with your function and give it a whirl.
I had in fact thought about using #some_label: as both methods would not create an error, something like command not found under normal running but I see your point.
And of course it's a hack, as I always quote "if there is a back door I will find it" and hacks by their nature are back doors....

Hi MadeInGermany...
(Hopefully this does not attach to the previous post.)

Copied and pasted your segment into my original code and it works well.

Thanks...

Bazza...

Moderator comments were removed during original forum migration.
goto() { . <(sed "/^$1"'/,$!d' $0); }
1 Like

There are other versions on the net using 'sed'.
I didn't want to use a third party utility at all, only a POSIX shell.
Much like most of my uploads recently.
MadeInGermany's alteration was a major improvement without resorting to a third party utility.

Anyway, I think it's better to exclude a temporary file
how about:

mapfile -s"$(grep -n "^$1" $0 | cut -d: -f1)" <$0
. <(echo "${MAPFILE[@]}")

without testing

prompted label option without space

#first:
#L1:

Hi nezabudka...

AMIGA:amiga~> bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)
Copyright (C) 2007 Free Software Foundation, Inc.
AMIGA:amiga~> mapfile
-bash: mapfile: command not found
AMIGA:amiga~> _

And it uses grep and cut which defeats the object of the OP.

1 Like

here I forgot to give explanations for the uninitiated, I apologize
call the function like this

goto \#first:
goto \#L1:

Haha, pure sacrilege this thread :+1: , Edsger must be turning in his grave :slight_smile:

2 Likes

This topic was automatically closed 283 days after the last reply. New replies are no longer allowed.