bug-bash
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Bash 5.2 breaks our Arch Linux devtools


From: Martin D Kealey
Subject: Re: Bash 5.2 breaks our Arch Linux devtools
Date: Thu, 16 Feb 2023 11:45:04 +1000

On Wed, 15 Feb 2023 at 23:29, Tobias Powalowski via Bug reports for the GNU
Bourne Again SHell <bug-bash@gnu.org> wrote:

> Hi,
> latest 5.2.x seems to have introduced a change in shopt extglob:
> https://gitlab.archlinux.org/archlinux/devtools/-/merge_requests/133
> I'm not sure if my proposed fix for this is correct or if this is just a
> bug in bash 5.2.x not checking the function for shopt first before bailing
> out.
> Repeat-By:
>  Sample code from our gitlab:
> % bash <<'EOF'
> function x() {
>   shopt -s extglob
>   mapfile -t packages < <(
>     printf "%s\n"
> "dir"/"dir"/"dir"/"{targetname}"-"${targetver}"-"${targetarch}".pkg.tar?(.!(sig|.*))
>   )
>   shopt -u extglob
> }
> x
> EOF
>
> Results in:
>
> bash: line 3: syntax error near unexpected token `('
>
> bash: line 3: `mapfile -t packages < <(printf "%s\n"
>
> "dir"/"dir"/"dir"/"{targetname}"-"${targetver}"-"${targetarch}".pkg.tar?(.!(sig|.*)))'
>
>
> Fix:
>
> Putting shopt options outside the function, but is this the wanted
> behaviour?
> Thanks for clarification,
> greetings
> tpowa
> --
>

That's not a change in 5.2, as extglob has always worked that way. However
what might have changed is whether extglob was already enabled elsewhere in
your script, or acquired from a setting in the environment.

As others have noted, when the “shopt -s extglob” command is executed, it
changes how subsequent commands are parsed, and since compound commands are
parsed in their entirety before they begin executing, changes to parser
settings made by commands inside a compound command cannot have any
influence on how any part of the compound command itself is parsed.

With a function the execution is further split into two steps: after a
function definition has been parsed, the definition must be executed (to
register the function name), and then when the function name is invoked
(from elsewhere in the script), the body of the function is executed. This
3rd step is clearly far too late to affect the first step.

Given that the parser mode is global, I would strongly recommend putting
shopt -s extglob right at the start of the script after the #!/bin/bash
line, along with other commands that can affect parsing, such as shopt -s
compat*XX*, shopt -s expand_aliases, set -o braceexpand, or set -o onecmd.

Simply putting «shopt -u extglob» after your function isn't right either,
since the remainder of the script might actually need it turned on, and
turning it off would break it.

There's no good reason to turn off extglob if you're writing a new script,
as it only affects the validity of some very weird corner cases.

  # Without extglob this is a function definition;
  # with extglob it's an empty glob followed by some args, followed by the
«}» at the start of the next command.
  @() { echo In @ func ; }

-Martin

PS: consider

make_toggle() {
  if (($#))
  then toggle() { echo "It's On" ; make_toggle ; }
  else toggle() { echo "It's Off" ; make_toggle -; }
  fi
}
# toggle does not exist here
def_toggle
# toggle now exists


reply via email to

[Prev in Thread] Current Thread [Next in Thread]