On Sat, Oct 30, 2021 at 7:07 PM Robert Elz <k...@munnari.oz.au> wrote: > > What POSIX says about this (which you probably know already) is: > > A loop shall enclose a break or continue command if the loop > lexically encloses the command. A loop lexically encloses a > break or continue command if the command is: > > [and just paraphrasing the conditions] > > - same exxecution environment (ie: not in a subshell) > - inside a compound list associated with a loop (including > the test list for while/until) > - not in the body of a function ... > > (more or less the obvious useful definition of lexically enclosing). > > That is the case in which break & continue are required to work. > > It goes on to say: > > If n is greater than the number of lexically enclosing loops > and there is a non-lexically enclosing loop in progress in the > same execution environment as the break or continue command, it is > unspecified whether that loop encloses the command. > > In your example, the number of lexically enclosing loops is 0, 'n' is 1, > so the shell is allowed to break from the loop, but not required to. >
Yes, I read all about this, thanks for the summary. > Or in other words, you should not write code like that, because it > is not guaranteed to work. Pity. But at least for now, (in bash, not other shells) I can place the function call between `shopt -s compat43' and `shopt -u compat43' and have the behavior I want without side effects (I believe). > > > oguzismailuy...@gmail.com said: > | `break' is not a keyword in the shell, but a special command. > > That's true. However, 99% of script writers don't see it that way, > they believe it is just like "if" or "while" or "done" or "return". > > That's why the "This is counterintuitive." I would guess - in most > cases, the issue isn't quite like yours, but more like > > f() { > for x in a b c; do > for y in 1 2 3; do > case "$x$y" in > (b3) break;; > (a2) continue 2;; > (c1) break 3;; > esac > done > done > } > > and then called something like > > for i in 1 2 3 4 5 6 > do > echo $i; f > done > > and people wonder why that loop never iterates the 2nd time (prints just 1). > > All this because the script author probably thought that they were > writing C, and the b3 break is for the case statement, a2 continue > is the y loop, and c1 break the x loop... > > They can be taught that that's wrong, break/continue do nothing for > case statements, and don't count them - but they simply refuse to believe > that whatever happens inside the function should affect the caller's > flow - an error from the "break 3" is something they can understand, > as is just ignoring the "overflow", but not more than that. Yeah. Not about break/continue, but I met many complaining about how there should be spaces around `[' and `]', how `if [ grep foo file ] ...' never reaches the else part, etc. and it's all tiresome. Thankfully I'm not writing a shell. > > For people who don't believe that all programming languages should work > the same way (usually the same way as the one they learned first) this > isn't necessarily as important - but that's a tiny majority of people. > > kre > > ps: the NetBSD shell continues to work the way that you want, and does > so by deliberate choice - our test suite has a whole stack of tests to > make sure this continues to all work "correctly" (doesn't accidentally > get changed). > I know, it's great. Though I still couldn't figure out how to have a command run on login and it drives me mad.