TE
TechEcho
Home24h TopNewestBestAskShowJobs
GitHubTwitter
Home

TechEcho

A tech news platform built with Next.js, providing global tech news and discussions.

GitHubTwitter

Home

HomeNewestBestAskShowJobs

Resources

HackerNews APIOriginal HackerNewsNext.js

© 2025 TechEcho. All rights reserved.

Goto in Bash (2012)

93 pointsby davidcollantesalmost 2 years ago

23 comments

arthur2e5almost 2 years ago
This reminds me of the Thompson shell goto, which is an external(!) program that messes with its parent&#x27;s file descriptors looking for `: label`.<p>See manpage at <a href="https:&#x2F;&#x2F;etsh.nl&#x2F;man&#x2F;_goto.1.html" rel="nofollow noreferrer">https:&#x2F;&#x2F;etsh.nl&#x2F;man&#x2F;_goto.1.html</a> and source code at <a href="https:&#x2F;&#x2F;github.com&#x2F;eunuchs&#x2F;tsh&#x2F;blob&#x2F;master&#x2F;goto.c">https:&#x2F;&#x2F;github.com&#x2F;eunuchs&#x2F;tsh&#x2F;blob&#x2F;master&#x2F;goto.c</a>.<p>See, history can give you a more inert syntax. And maybe a new way of thinking about how to make this thing... I would love to have a more robust version to do C-style goto cleanups.
评论 #36987271 未加载
mikepurvisalmost 2 years ago
Since he mentions this being for a work thing, how I&#x27;ve handled a similar situation (long running shell thingies) is:<p>Break up the script into steps, and place them in order in a dot-d style folder, like 1.foo.sh, 2.bar.sh, 3.baz.sh. Have a separate _context.sh which supplies the upfront variables or whatever are needed for each step. Ensure that each step can run on its own with just the context sourced. Then have a run.sh in the folder above that sources the context and the steps in order.<p>Now, that said, typically these kinds of things are dataflow or even buildsystem-adjacent, so I&#x27;ve also experimented with doing them in CMake (intermediate products managed with add_custom_target) or as Nix derivations (intermediate products are input-addressed in the Nix store), but I&#x27;d love to be aware of other tools that are better for expressing this kind of thing.
评论 #36986499 未加载
评论 #37006793 未加载
评论 #36994178 未加载
评论 #36990543 未加载
ggeorgovassilisalmost 2 years ago
He writes &quot;prepare to cringe&quot; and he is not wrong. As far as I understand, this technique implements GOTO by reading the source code (again) into memory, filtering out everything before the target label and evaluating the remaining source code. I think this doesn&#x27;t preserve state, variables etc. so not really a GOTO. But interesting technique.<p>edited for clarity
评论 #36985896 未加载
评论 #36986585 未加载
tavisoalmost 2 years ago
It&#x27;s a funny trick, but you could probably also use setjmp and longjmp with ctypes.sh :-)<p><a href="https:&#x2F;&#x2F;github.com&#x2F;taviso&#x2F;ctypes.sh">https:&#x2F;&#x2F;github.com&#x2F;taviso&#x2F;ctypes.sh</a>
评论 #36988611 未加载
sltkralmost 2 years ago
Instead of:<p><pre><code> sed -n &quot;&#x2F;$label:&#x2F;{:a;n;p;ba};&quot; </code></pre> I think it&#x27;s more idiomatic to do:<p><pre><code> sed -n &quot;&#x2F;$label:&#x2F;,$ p&quot; </code></pre> Or even:<p><pre><code> sed &quot;0,&#x2F;$label:&#x2F;,$ d&quot; </code></pre> Which deletes the label itself, so you don&#x27;t need the subsequent `grep -v &#x27;:$&#x27;`, but then you also aren&#x27;t allowed to put any statements on the same line as the label.
jrm4almost 2 years ago
Honestly, I <i>love</i> this.<p>Precisely because there&#x27;s too much gatekeeping in programming and learning etc. Give people sharp knives and let them break things
评论 #36987786 未加载
评论 #36987318 未加载
tragomaskhalosalmost 2 years ago
BAT files writing other BAT files was often the only way to get scripting workflows done on primordial Windows versions, but chaos typically ensued if you attempted to rewrite the file you were presently running, as it appears that cmd didn&#x27;t do anything fancy like read the whole file into memory before processing it (presumably due to the draconian memory limits people laboured under back then)
评论 #36988049 未加载
评论 #36993418 未加载
js2almost 2 years ago
&gt; It runs sed on itself to strip out any parts of the script that shouldn’t run, and then evals it all.<p>How I have done this is:<p>1. Put all the steps in functions.<p>2. Have a main function that calls all the other functions in order.<p>3. If given an argument, the main function skips all the functions up to that one.
评论 #36987508 未加载
vidarhalmost 2 years ago
If you&#x27;re going to do that, you might as well go the whole hog and implement INTERCAL&#x27;s &quot;come from&quot;[1] for maximal evil.<p>[1] <a href="https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;COMEFROM" rel="nofollow noreferrer">https:&#x2F;&#x2F;en.wikipedia.org&#x2F;wiki&#x2F;COMEFROM</a>
评论 #36986342 未加载
knomealmost 2 years ago
the author mentions in a note that bash was complaining and that they might put the labels in comments to dodge the issue. They might also be able to change the label format to `: label`. `:` just returns true regardless of what parameters you pass it, so it could still look &quot;labelish&quot; without having to use an actual comment.
Joker_vDalmost 2 years ago
That&#x27;s one of the few places where it would be appropriate to store the current execution point somewhere in &#x2F;var&#x2F;cache or &#x2F;var&#x2F;lock and write the script so that it would look there at launch and dispatch accordingly.
8chanAnonalmost 2 years ago
&quot;GOTO is considered harmful&quot;. This kind of thinking just makes me want to run off screaming into a paper bag. Language developers are, in many ways, the modern aristocrats telling us what we can&#x27;t or should not do. I still miss assembly language.
评论 #36986326 未加载
评论 #36986128 未加载
评论 #36986715 未加载
评论 #36989462 未加载
zzo38computeralmost 2 years ago
I had mostly done some short stuff in bash that does not need much flow controls and loops etc; most programming I will use C instead, which does have goto and is sometimes useful even though usually the other flow controls are better. My own programming language designs do have a goto command because it is sometimes useful; the Free Hero Mesh programming language has both goto and gosub, in addition to the structured flow controls (if&#x2F;then, begin&#x2F;while&#x2F;repeat, etc).<p>The way is done in that article doesn&#x27;t seem best way to do; modifying the shell itself to seek the shell script file for it seem to be better in my opinion, or perhaps using the &quot;enable&quot; command to add your own built-in &quot;goto&quot; command (although I don&#x27;t know if the API supports that). Another message on here mentions an external program messing with the file descriptors, but does bash use a consistent file descriptor number for the shell script file with which this will work?
t0astbreadalmost 2 years ago
That&#x27;s neat but doesn&#x27;t `case` support fallthrough? So I expect you could just put your script in one big `case` statement and skip to the branch you need.
评论 #36994125 未加载
ectosphenoalmost 2 years ago
Make first argument your step&#x2F;label. Each step can have its own command line. Exec yourself. Accomplishes same thing without being scary.
Borborygymusalmost 2 years ago
And I did cringe, and then I thought it looked kinda fun. It would literally never have occurred to me in a million years to try to start a shell script half way though - so trapped am I in the paradigm of the familiar.<p>As for the script that takes several days and often breaks half way through... sounds like what Makefiles are for to me.
_aaedalmost 2 years ago
Thanks I hate it
otikikalmost 2 years ago
Some men just want to watch the world burn.
alganetalmost 2 years ago
This is silly. Whatever can be done with this approach can be better written with just functions.
38almost 2 years ago
after many years, I learned that usually shell scripts are only good for the most basic of uses. here is a similar program in Go that doesn&#x27;t require any hacks:<p><pre><code> package main import &quot;os&quot; func main() { var x int switch len(os.Args) { case 1: goto start default: switch os.Args[1] { case &quot;foo&quot;: goto foo case &quot;mid&quot;: goto mid } } start: x = 100 goto foo mid: x = 101 println(&quot;This is not printed!&quot;) foo: if x == 0 { x = 10 } println(&quot;x is&quot;, x) }</code></pre>
ufoalmost 2 years ago
Does this also works inside if and while blocks?
zapsalmost 2 years ago
This is the best worst thing I’ve ever seen
评论 #36993880 未加载
cramjabsynalmost 2 years ago
what have you done…