Bash parameter expansion (remove largest trailing match, remove largest leading match, pattern replacement) does not work

2020-08-29 Thread Bruce Lilly
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: netbsd
Compiler: gcc
Compilation CFLAGS: -O2 -D_FORTIFY_SOURCE=2 -I/usr/include
-Wno-parentheses -Wno-format-security
uname output: NetBSD cq60-615dx.blilly.net 9.0 NetBSD 9.0 (GENERIC)
#0: Fri Feb 14 00:06:28 UTC 2020
mkre...@mkrepro.netbsd.org:/usr/src/sys/arch/amd64/compile/GENERIC
amd64
Machine Type: x86_64--netbsd

Bash Version: 5.0
Patch Level: 17
Release Status: release

Description:
   Bash parameter expansion (remove largest trailing match, remove
largest leading match, pattern replacement) does not work
Tested on OpenSUSE Leap 15.2, bash version 4.4.2.3(1)-release
(x86_64-suse-linux-gnu)
OpenBSD 6.7 bash version 5.0.17(1)-release (x86_64-unknown-openbsd6.7)
NetBSD 9.0 bash version 5.0.17(1)-release (x86_64--netbsd)
FreeBSD 12.1-STABLE bash version 5.0.18(2)-release (amd64-portbld-freebsd12.1)

Same results in all cases; this report posted from NetBSD 9.0.

As an example, consider constructing a path from components; the full
path should
have a single separator (slash), so any stray slashes at the tail of
the first part or the
start of the last part should be elided.  There are many ways that
that can be done,
the "Repeat By" section demonstrates only a few examples.

Relevant manual sections are:
https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Shell-Parameter-Expansion
https://www.gnu.org/savannah-checkouts/gnu/bash/manual/bash.html#Pattern-Matching

Repeat-By:
 $ bash shellbug
Running bash from /usr/pkg/bin/bash
Bash version 5.0.17(1) release GNU
dir=/foo/bar/baz/// separator1=/ separator2(octal escape)=\057
number0=* number1=+ pattern1=${number1}(${separator1})=+(/)
pattern2=${number0}([${separator2}])=*([\057]) base=///grimble/pritz
path=${dir%%${pattern1}}${separator1}${base##${pattern2}}=${dir%%+(/)}/${base##*([\057])}=/foo/bar/baz///grimble/pritz
path=${dir/%${pattern1}/${separator1}}${base/#${pattern2}/}=${dir/%+(/)//}${base/#*([\057])/}=/foo/bar/baz//grimble/pritz

Fix:
(demonstrates how a functioning shell handles exactly the same cases):
$ ksh93 shellbug
Running ksh93 from /usr/pkg/bin/ksh93
$Id: Version AJM 93u+ 2012-08-01 $
dir=/foo/bar/baz/// separator1=/ separator2(octal escape)=\057
number0=* number1=+ pattern1=${number1}(${separator1})=+(/)
pattern2=${number0}([${separator2}])=*([\057]) base=///grimble/pritz
path=${dir%%${pattern1}}${separator1}${base##${pattern2}}=${dir%%+(/)}/${base##*([\057])}=/foo/bar/baz/grimble/pritz
path=${dir/%${pattern1}/${separator1}}${base/#${pattern2}/}=${dir/%+(/)//}${base/#*([\057])/}=/foo/bar/baz/grimble/pritz



Re: Bash parameter expansion (remove largest trailing match, remove largest leading match, pattern replacement) does not work

2020-08-29 Thread Bruce Lilly
Robert,
Did you look at the relevant bash manual pages linked in the bug report?


>
>


Re: Bash parameter expansion (remove largest trailing match, remove largest leading match, pattern replacement) does not work

2020-08-29 Thread Bruce Lilly
On Sat, Aug 29, 2020, 13:48 Robert Elz  wrote:

> Date:Sat, 29 Aug 2020 13:33:37 -0400
> From:    Bruce Lilly 
> Message-ID:   n...@mail.gmail.com>
>
>   | Did you look at the relevant bash manual pages linked in the bug
> report?
>
> Enough to know that [\057] doesn't mean what you seem to believe it should.
>
> kre
>

Evidently not enough to see the specifications for pattern matching...

>
>


Re: Bash parameter expansion (remove largest trailing match, remove largest leading match, pattern replacement) does not work

2020-08-29 Thread Bruce Lilly
Please don't assume that something output by printf (without quoting) for
clarity is representative of actual expansion by the shell when properly
quoted.

On Sat, Aug 29, 2020, 14:52 Koichi Murase  wrote:

> 2020-08-29 23:47 Bruce Lilly :
> > Description:
> > Bash parameter expansion (remove largest trailing match,
> > remove largest leading match, pattern replacement) does not work
>
> In short, (1) ``octal escape \057'' doesn't have special meaning in
> Bash glob patterns.  `[\057]' means just one of a literal backslash or
> digits 0, 5, or 7.  (2) You need to set `shopt -s extglob` to use
> extended glob patterns like `+(...)' and `*(...)'.  Please look at the
> paragraph above the list of extended patterns in the manual.
>
> --
> Koichi
>


Re: Bash parameter expansion (remove largest trailing match, remove largest leading match, pattern replacement) does not work

2020-08-29 Thread Bruce Lilly
Thanks for the pointer to "shopt"; I'll check when I get a chance.

On Sat, Aug 29, 2020, 14:52 Koichi Murase  wrote:

> 2020-08-29 23:47 Bruce Lilly :
> > Description:
> > Bash parameter expansion (remove largest trailing match,
> > remove largest leading match, pattern replacement) does not work
>
> In short, (1) ``octal escape \057'' doesn't have special meaning in
> Bash glob patterns.  `[\057]' means just one of a literal backslash or
> digits 0, 5, or 7.  (2) You need to set `shopt -s extglob` to use
> extended glob patterns like `+(...)' and `*(...)'.  Please look at the
> paragraph above the list of extended patterns in the manual.
>
> --
> Koichi
>


Re: Bash parameter expansion (remove largest trailing match, remove largest leading match, pattern replacement) does not work

2020-08-29 Thread Bruce Lilly
Unfortunately, because bash is GPL, I can't post the copyrighted script
which is covered by a non-GPL license.

On Sat, Aug 29, 2020, 15:22 Ilkka Virta  wrote:

> On Sat, Aug 29, 2020 at 9:56 PM Bruce Lilly  wrote:
>
>> Please don't assume that something output by printf (without quoting) for
>> clarity is representative of actual expansion by the shell when properly
>> quoted.
>>
>
> If you don't want people to assume (and you shouldn't, if you want them to
> help you),
> you'd better post the actual script you use, and not just something output
> by printf.
> Without that, it's impossible to check what quoting you used, or to
> reproduce the issue.
>
>


Re: Bash parameter expansion (remove largest trailing match, remove largest leading match, pattern replacement) does not work

2020-08-29 Thread Bruce Lilly
On Sat, Aug 29, 2020, 15:40 Koichi Murase  wrote:

> Don't worry.  In this case, the GPL doesn't apply.  Please read the
> following Q&A.
>
> https://www.gnu.org/licenses/gpl-faq.en.html#IfInterpreterIsGPL
>
> Even if your original `shellbug' is licensed under something other,
> and it prohibits to make it public, you can still create another
> script to reproduce the same issue.  [...]
>
It's a bit more complicated than that; if, for example, some excerpt ended
up in regression tests, there would be a question about whether or not
there was a copyright violation.  As I understand the GPL (IANAL), it
requires all parts of a "work" to be GPL'd, and that wouldn't be possible
for any parts of the script that ended up in bash regression tests.


Re: Bash parameter expansion (remove largest trailing match, remove largest leading match, pattern replacement) does not work

2020-08-29 Thread Bruce Lilly
On Sat, Aug 29, 2020, 15:27 Koichi Murase  wrote:

>  I assumed that you have written like
>
>   separator2='\057'
>   pattern1="${number1}(${separator1})"
>
> because otherwise, it doesn't work with ksh93 either.
>
You are correct.

To explain it in more detail, first, these parameter expansions work
> for me with separator1='/'.  The pattern that you constructed from
> separator2='\057' is just not supported by Bash.

That's surprising, as octal and hexadecimal escapes are fairly common.

  Next, you specify
> exactly the same script `shellbug' to both Bash and ksh93, so I could
> assume that you are missing the Bash-specific `shopt -s extglob' in
> the script because otherwise, ksh93 would have complained it.  That is
> all what I can guess from your original post.
>
Yes, I'm still looking into that (along with updating a couple of FreeBSD
machines, eating lunch, and monitoring a couple of downloads).  I'll
obviously have to wrap the "shopt" bit in a wrapper; is there some minimum
bash version that supports it?

>
>


Re: Bash parameter expansion (remove largest trailing match, remove largest leading match, pattern replacement) does not work

2020-08-29 Thread Bruce Lilly
On Sat, Aug 29, 2020 at 4:53 PM Koichi Murase  wrote:
[...]
> That's an interesting discussion.  I don't know how you define the
> "work", but basically GPL only affects the derivative
> programs/software but not all the "work" including the output of the
> programs or the knowledge obtained in running/developing the code.

I'm using it in the sense of the GPL, as in the part of the preamble:
"software and other kinds of works".
It's not clearly defined; vagueness is one of the problems with the GPL.
I'm assuming that for bash it basically means everything that's included
in the distributed package.  "Everything" is basically what GPL 3 section
5c says must be covered by the GPL.

[...]
> Otherwise, anyone who
> read a GPL code in the past cannot write any non-GPL programs because
> one cannot prove the experience of reading the GPL code doesn't affect
> any code that he/she writes thereafter.  I sometimes hear that someone
> avoids hiring programmers who have read a GPL code in the past for
> defensive purposes, but I believe it's a matter of degree.

That's basically the issue, and it goes both ways (i.e. also people
writing GPL'ed code based on non-GPL source (or slapping a GPL
license on non-GPL code); there's a rather famous case
http://undeadly.org/cgi?action=article&sid=20070913014315 ).

> 2020-08-30 5:07 Bruce Lilly :
> > That's surprising, as octal and hexadecimal escapes are fairly
> > common.
>
> Yes, I know that it is confusing to those who are familiar with modern
> Perl-style regular expressions.  But historically, POSIX regular
> expressions do not support the backslash escape sequences in bracket
> expressions `[...]'.  The backslash escape sequences in bracket
> expressions were the extension historically.  As far as I know, in
> POSIX, only awk supports backslash sequences in regular expressions.

Actually, it works (portably) with
separator2=$'\057'

> Bash 2.02 supports `shopt -s extglob', so you can assume every Bash
> has the support.  If you are still failing to get an expected
> behavior, you can just put the line `shopt -s extglob' in the
> beginning of the script.  In the case of the above mentioned reduced
> case, you can write like this:

The magic "shopt" incantation was indeed the key: thank you.

I guess this can be considered closed.

It would be nice, however, if there were an environment variable that
could cause bash to default to extglob.  My concern is some variants of
make that send recipes line-by-line to a shell, in which case each line
might need to be prefixed by a test for ${BASH_VERSION} and the
shopt builtin.



Re: Bash parameter expansion (remove largest trailing match, remove largest leading match, pattern replacement) does not work

2020-08-29 Thread Bruce Lilly
On Sat, Aug 29, 2020 at 9:12 PM Lawrence Velázquez  wrote:

> (a) $'...' is not POSIX. For instance, dash does not recognize it.

dash also doesn't have adequate pattern matching for the example
task (building a path while ensuring no empty components); it
has no way to specify one-or-more (or zero-or-more) occurrences
of a pattern such as a slash.