It has been brought to my attention (off list) that the change to the way that the ! command (reserved word) is permitted to be used in /bin/sh has affected one use case that wasn't anticipated - that is, the possibility never occurred to me.
That is defining a function as func() ! simple_command no longer works, though we still permit func() simple_command (Both of which are non-standard extensions to the POSIX sh definition.) The change happened because we actually permit func() command and one of the possibilities for "command" is "simple_command" and simple_command (used to) permit a leading ! reserved word, and does not any more. ! is now only permitted in (at the start of) a pipeline, which in normal use is the only place it makes sense (and is what the standard defines) and a pipeline is not one of the elements of a command (rather a command is one of the elements of a pipeline.) I see four possibilities to deal with this... 1. leave it as it is now, func() ! simple_command is non-standard usage, func() { ! simple_command; } works, and is standard (works everywhere). 2. Change the definition of a function definition (in our sh) from name "()" command to name "()" pipeline which would automatically permit the "! simple_command" case, and would also permit func() ls | wc -l and similar. It would make it harder to include a function definition in a pipeline however, and that is a standard blessed use case, not that it is a useful endeavour (definitions do not read or write anything, so defining a function with stdin or stdout redirected from/to some other command isn't really useful - and what's more isn't guaranteed to work anyway, as pipelines are permitted to be executed in sub-shells, and if they were, the function definition, if embedded in a pipeline, would never become visible in the shell.) If we go this route, we could instead permit and_or (instead of command or pipeline) - though I have not thought through the implications of that one. Going all the way and allowing a list would break too much I suspect. [ and_or would allow "func() command && other" to be a definition, rather than meaning "if the definition succeeds (they always do) run "other", Allowing "list" would mean "func() command; command & command" would all be a definition - but in that case, I suspect the definition would continue growing until EOF, there would be nothing to stop it, where "EOF" here includes the end of some embedding syntax element, if any. ] 3. Change the definition of a function definition (in our sh) to name "()" [ "!" ] command which would put back the functionality that was removed - and a little more, as that would also permit func() ! { command; command...; } and similar. This one has least effect (of any change) upon the language the shell implements, but would be one more hack... If we did this we might actually want to make it name "()" [ "!" [ "!" ] ] command for consistency with what we allow in pipelines (again, non-standard.) 4. Put back BOGUS_NOT_COMMAND (allowing ! in bizarre places) or perhaps just in the (still bizarre) case in simple_command. This one I would really prefer if we not do. Which of those do people think best? Does anyone (else) use the func() ! command method of defining a function? kre ps: none of this has anything at all to do with using a function after it is defined. For that a function is just one case of a simple_command.