Martin von Gagern wrote: > I've found out that extglobs behave differently in different > constructs. To avoid syntax errors, the always have to be > enabled at parse time. > For comparison constructs like ``[[ $v == a@(a|b|c)c ]]'' this > is enough. For case constructs like ``case $v in a@(a|b|c)c)'' > the extglob shopt has to be set at runtime as well. This is kind > of inconsistent.
OK, I guess this is due to the following difference: execute_cmd.c:3225-3231 in execute_cond_node: > int oe; > oe = extended_glob; > extended_glob = 1; > result = binary_test (cond->op->word, arg1, arg2, > TEST_PATMATCH|TEST_ARITHEXP) > ? EXECUTION_SUCCESS > : EXECUTION_FAILURE; > extended_glob = oe; execute_cmd.c:2931 in execute_case_command: > match = strmatch (pattern, word, FNMATCH_EXTFLAG|FNMATCH_IGNCASE) != > FNM_NOMATCH; What's interesting is what you don't see here: the case command doesn't temporarily set extended_glob to 1 as the cond node does. I guess this is where the different behaviour at runtime comes from. Is this difference intentionally, or is this a bug? If it is a bug, the attached patch should fix it, although it might introduce other issues. At least for my example script, the patch does its job. I'm a bit surprised that execute_cond_node seems to unconditionally enable the extended glob mode. I don't see any check whether the thing has been parsed as an extended glob in the first place. Is this because things that look like extended globs will always be invalid syntax if extglob is off? So that if anything got parsed successfully and still looks like an extended glob, the code can be sure it was parsed as an extended glob? In that case, is there any point in not always enabling extended globs, except if you are testing the portability of your script? If so, I'll second the request to always enable them, but I have some doubts that's the case. As an alternative to my patch, one could maybe move all this temporary extglob stuff to the function definitions. I.e. a function defined with extglob on will also have extglob on when executed, and vice versa. This might break some compatibility, though, especially for subshells. And simply saving and restoring functins by listing their definition would become a trouble as well. So it's just a thought so far. Greetings, Martin
Allow use of extended globs in case constructs at runtime, even if the extglob shopt is not set. 2009-10-01 Martin von Gagern References: http://thread.gmane.org/gmane.comp.shells.bash.bugs/13518 Index: bash-4.0/execute_cmd.c =================================================================== --- bash-4.0.orig/execute_cmd.c +++ bash-4.0/execute_cmd.c @@ -2915,6 +2915,7 @@ execute_case_command (case_command) QUIT; for (list = clauses->patterns; list; list = list->next) { + int oe; es = expand_word_leave_quoted (list->word, 0); if (es && es->word && es->word->word && *(es->word->word)) @@ -2928,8 +2929,11 @@ execute_case_command (case_command) /* Since the pattern does not undergo quote removal (as per Posix.2, section 3.9.4.3), the strmatch () call must be able to recognize backslashes as escape characters. */ + oe = extended_glob; + extended_glob = 1; match = strmatch (pattern, word, FNMATCH_EXTFLAG|FNMATCH_IGNCASE) != FNM_NOMATCH; free (pattern); + extended_glob = oe; dispose_words (es);