select syntax violates the POLA
Configuration Information [Automatically generated, do not change]: Machine: x86_64 OS: netbsd Compiler: gcc Compilation CFLAGS: -O2 -I/usr/local/include -D_FORTIFY_SOURCE=2 -I/usr/include uname output: NetBSD eddie.starwolf.com 9.99.81 NetBSD 9.99.81 (EDDIE) #9: Tue Mar 23 19:13:25 PDT 2021 greyw...@eddie.starwolf.com:/sys/native/compile/EDDIE amd64 Machine Type: x86_64--netbsd Bash Version: 5.1 Patch Level: 4 Release Status: release Description: The 'select' directive's syntax does not correspond to the rest of the shell's syntax. I am not sure if this is by design; if it is, let me know and I'll go away. The following is valid shell code: d=($(ls /usr/src/pkg/*/$1)); n=${#d[@]}; if ((n > 1)); then { echo "Ambiguous dir specification"; exit 1; } else { dir=${d[0]}; } fi; cd ${dir} && make clean && { make update || make install; } I'd like to replace the first part of the if/else/fi with: if ((n > 1)); then { select dir in ${d[@]}; do { break; } done; } else { ... ...but select breaks on the "} done;" syntax that works with, e.g., while sleep 5; do { date; } done; until [ -f ${tmpfile} ]; do { sleep 5; } done; for dir in ${d[@]}; do { echo ${dir}; } done; This violates the POLA, from my point of view. Repeat-By: d=($(ls /usr/src/pkg/*/$1)); select dir in ${d[@]}; do { break; } done;
Re: select syntax violates the POLA
On 4/1/2021 9:16, konsolebox wrote: On Thu, Apr 1, 2021 at 11:25 PM wrote: if ((n > 1)); then { echo "Ambiguous dir specification"; exit 1; } else { dir=${d[0]}; } fi; The grouping is unnecessary or should be separate from the first class syntax. Bash is not C or Go and shouldn't be written like it. I didn't ask for your opinion on my coding style. It's worked correctly for 25 years. I have my reasons.
Re: select syntax violates the POLA
On 4/1/2021 9:58, Robert Elz wrote: Date:Thu, 1 Apr 2021 11:36:14 -0400 From:Greg Wooledge Message-ID: | On Thu, Apr 01, 2021 at 01:36:59AM -0700, greyw...@starwolf.com wrote: | > The following is valid shell code: | > | > d=($(ls /usr/src/pkg/*/$1)); | | Syntactically valid, but semantically wrong Mr. Elz! Long time! I remember reading your posts 30 years ago! [ much other ado elided ] | "${d[@]}" with quotes. Again, yes, but in practice here, not needed. | What purpose do the extra curly braces serve? Good question, wondered that myself. Note that if they were omitted the odd syntax issue wouldn't have arisen, as the done would follow "break;" and be recognised. Unfortunately the way bash has implemented arrays, $d[@] doesn't do The Right Thing. Or do you mean my coding style (which has been valid for over 25 years)? (why's everyone bagging on my style and ignoring my original point, the outlying brokenness, anyway?) I started using the curly braces because every (worthwhile) editor has a paren-match function which shows you the matching brace at the other end, and I was tired of searching for which conditional component (while, if, for, and so on) was missing its closing word. This helps me immensely. After all that, and ignoring select's syntax (it was invented by ksh, long long ago, and isn't going to change) it is a dumb interface that can always be coded better using other mechanisms. And when you do that you can allow for much more flexible input than just the line number the select demands. Indeed, I have written such animals from scratch; I just thought I'd try out select and was astonished when select x in ${list}; do { break; } done; was the only one that failed. If you avoid select, and avoid arrays, then any Bourne style shell will work. So, do that. I will also note that the arrays don't give me grief in the least. :) kre Thank you so much for your response! You got exactly what I was after! --*greywolf;
Re: select syntax violates the POLA
Hi, Chet! I've read a lot of your posts long ago, as well! On 4/1/2021 8:57, Chet Ramey wrote: It's more like `select' doesn't inherit some of the shell's special cases. select dir in ${d[@]}; do { break; } done; >> ...but select breaks on the "} done;" syntax Yes, you need a list terminator so that `done' is recognized as a reserved word here. `;' is sufficient. Select doesn't allow the `done' unless it's in a command position. Some of the other compound commands have special cases, mostly inherited from the Bourne shell, to allow it. Firstly, thank you for your concise reply. I discovered that making it '}; done;' as you suggested here worked, shortly after my broken astonishment :). kre mentioned that it's a ksh holdover. This explains a great many things considering how horribly broken I have found ksh to be (and the weak arguments supporting that brokenness; among them, the need to say 'fg %4' instead of merely being able to say '%4'; the requirement to have ${var[ix]} instead of honouring $var[ix] with regard to arrays is another one). Lastly, thanks for not bagging on my coding style. It was somewhat intentional, somewhat accidental when I started using it 25 years back. Being able to paren-match my for-in-do-done, while/until-do-done, if-elif-else-fi has been a timesaver. It not only helps me spot missing closures, it helps me spot missing quotes. [I think the only thing I wish would be enhanced and accepted further was for it to work with case-esac, but that hasn't changed in 25 years, either, and it's minor, so I'm not holding my breath. :) ] Cheers, --*greywolf;
Re: select syntax violates the POLA
On 4/1/2021 16:03, Robert Elz wrote: Partly because if you didn't use the braces, the issue wouldn't have arisen. (And because to most of us it just looks weird, kind of like people who write functions like f() {( commands to run in a subshell )} where the braces do nothing useful at all. and should just be omitted. Heh. Nope -- if it's to be subshelled, I do not use the braces around the parens. that's not an unreasonable use explanation. I find that a consistent style and correct indentation work well enough for this though. I have a consistent style and indentation ("correct" is subjective) :) ... so '} done' should work correctly, always, if the '}' is a reserved word, and a ';' or newline between them should not be needed. Which was why I was kind of taken aback when it failed. kre Thank you, again! --*greywolf;
Re: select syntax violates the POLA
On 4/4/2021 23:13, konsolebox wrote: On Sat, Apr 3, 2021 at 1:09 AM Robert Elz wrote: | [[ ]] and (( )) are a form of reserved words themselves Those are bash specials, and I am fairly sure that (( and )) will be operators, not reserved words (they cannot really be the latter, as ( and ) are operators) and I suspect that [[ and ]] might be as well, but there I'm not sure. operators and reserved words are quite different things. Operators (unquoted) are recognised as themselves wherever they appear. Stop suspecting and read the source code. Look at parse.y starting at line 2150. They are labeled as "Reserved words". [[ and ]] behave like reserved words requiring whitespace between themselves and their operands. (( and )) do not carry that restriction; within (( )), neither do any of */%^&|+- (or their respective OP=), nor == || && !. This effectively classifies (( )) as operators. But we've drifted considerably afield. --*greywolf;
Re: select syntax violates the POLA
On 4/1/2021 8:57, Chet Ramey wrote: Yes, you need a list terminator so that `done' is recognized as a reserved word here. `;' is sufficient. Select doesn't allow the `done' unless it's in a command position. Some of the other compound commands have special cases, mostly inherited from the Bourne shell, to allow it. I don't know that I'd call them "special cases" if sh has pretty much condoned it from the get-go; 'select' is the outlier, from my POV. --*greywolf;
Re: select syntax violates the POLA
On 4/2/2021 8:21, konsolebox wrote: That's not a rule but a special compromise. [[ ]] and (( )) are a form of reserved words themselves just like () and {} as they can be used multi-line but they aren't allowed to be adjacent to else et al without a semicolon. [[ ]], (( )), {}, and () are practically just commands with first-class parsing that consistently have to end with a semicolon if followed by another reserved word or command. I'd call it less a compromise than a mechanism; of all listed, {} represents a block of code in the current shell, () represents a block of code in a subshell... but if you want to go down that track, it's kind of interesting to note that {} on a single line demands a ; before the }, while () prohibits it. This also seems inconsistent to me, but not at the same level of egregious brokenness as select. --*greywolf;
Re: select syntax violates the POLA
On 4/5/2021 6:27, Chet Ramey wrote: On 4/5/21 5:06 AM, Greywolf wrote: but if you want to go down that track, it's kind of interesting to note that {} on a single line demands a ; before the }, while () prohibits it. This isn't true: $ ./bash -c '(echo a b c;)' a b c but it is the case that } is a reserved word, while ) is an operator. D'OH! You're right! I was thinking $ foo &; Can't put a semicolon after a null statement. My mistake. Carry on... --*greywolf;
Re: select syntax violates the POLA
On 4/5/2021 13:52, Chet Ramey wrote: On 4/1/21 5:40 PM, Greywolf wrote: Or do you mean my coding style (which has been valid for over 25 years)? Hey, if you want to go there, `select' has been in bash with its current syntax for longer than that. ;-) (A month over 27 years, if you're curious.) HAH! And I only just found about it very recently while perusing the man page! Go figure! In any case, I apologise if, at any point, I came across as hostile (never my intent), and I thank you for taking the time to parley. I've learned a few things. --*greywolf;
Re: select syntax violates the POLA
On 4/5/2021 14:21, Chet Ramey wrote: This presented an opportunity to marginally simplify the grammar, so it's a win all around. The change will be in the next devel branch push. You have my sincere gratitude. I did not expect so much to come of it. Chet --*greywolf;