Incorrect handling of echo in POSIX mode

2024-03-15 Thread Clint Hepner
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: darwin19.6.0
Compiler: gcc
Compilation CFLAGS: -g -O2
uname output: Darwin hemma.home 19.6.0 Darwin Kernel Version 19.6.0: Tue Jun 21 
21:18:39 PDT 2022; root:xnu-6153.141.66~1/RELEASE_X86_64 x86_64
Machine Type: x86_64-apple-darwin19.6.0

Bash Version: 5.2
Patch Level: 26
Release Status: release

Description:
In POSIX mode, echo incorrectly processes -e as an option unless xpg_echo 
is also enabled.

This is a regression from 3.2 (or possibly some 4.x versions, haven't 
tested), where --posix caused -e
to be treated correctly, even if it also enabled backslash processing.

   ~ % /bin/bash --posix
   [macOS warning elided]
   bash-3.2$ echo -e foo\\nbar
   -e foo
   bar



Repeat-By:

~/bash % bash
bash-5.2$ bash --posix -c 'echo -e foo\\nbar'
foo
bar
bash-5.2$ bash --posix -O xpg_echo -c 'echo -e foo\\nbar'
-e foo
bar


--
Clint Hepner




read with parameter expansion in here string

2013-11-22 Thread Clint Hepner
Configuration Information [Automatically generated, do not change]:
Machine: i386
OS: darwin13.0.0
Compiler: clang
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='i386' 
-DCONF_OSTYPE='darwin13.0.0' -DCONF_MACHTYPE='i386-apple-darwin13.0\
.0' -DCONF_VENDOR='apple' 
-DLOCALEDIR='/usr/local/Cellar/bash/4.2.45/share/locale' -DPACKAGE='bash' 
-DSHELL -DHAVE_CONFIG_H -DMA\
COSX   -I.  -I. -I./include -I./lib -I./lib/intl 
-I/private/tmp/bash-4vKN/bash-4.2/lib/intl  -DSSH_SOURCE_BASHRC
uname output: Darwin patikoija.local 13.0.0 Darwin Kernel Version 13.0.0: Thu 
Sep 19 22:22:27 PDT 2013; root:xnu-2422.1.72~6/REL\
EASE_X86_64 x86_64
Machine Type: i386-apple-darwin13.0.0

Bash Version: 4.2
Patch Level: 45
Release Status: release

Description:

An unquoted parameter expansion in a here string does not seem to 
conform with my understanding of how
read works with a local IFS override. Personally observed in bash 
3.2.51, 4.1.2 as well. I first learned
of this possible bug via http://stackoverflow.com/q/20144593/1126841.

Repeat-By:
$ var="hello:world"

# Case (1) I would expect "hello:world" in var1 if $var isn't split, or 
"hello"
# if it is. World splitting seems to occur after var1 is set, which 
doesn't
# seem to make sense.
$ IFS=: read var1 var2 <<< $var
$ echo "$var1"
hello world

# Case (2) Expected behavior, consistent with case (3)
$ IFS=: read var1 var2 <<< "$var"
$ echo "$var1"
hello

# Case (3) - no parameter expansion involved with the read
$ IFS=: read var1 var2 <<< hello:world
$ echo "$var1"
hello

# Case (4) - an explicit here document instead of a here string
$ IFS=: read var1 var2 < $var
> EOF
$ echo "$var1"
hello




Re: read with parameter expansion in here string

2013-11-22 Thread Clint Hepner

On Nov 22, 2013, at 10:04 AM, Pierre Gaston  wrote:

> 
> 
> 
> On Fri, Nov 22, 2013 at 4:22 PM, Clint Hepner  wrote:
> Configuration Information [Automatically generated, do not change]:
> Machine: i386
> OS: darwin13.0.0
> Compiler: clang
> Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='i386' 
> -DCONF_OSTYPE='darwin13.0.0' -DCONF_MACHTYPE='i386-apple-darwin13.0\
> .0' -DCONF_VENDOR='apple' 
> -DLOCALEDIR='/usr/local/Cellar/bash/4.2.45/share/locale' -DPACKAGE='bash' 
> -DSHELL -DHAVE_CONFIG_H -DMA\
> COSX   -I.  -I. -I./include -I./lib -I./lib/intl 
> -I/private/tmp/bash-4vKN/bash-4.2/lib/intl  -DSSH_SOURCE_BASHRC
> uname output: Darwin patikoija.local 13.0.0 Darwin Kernel Version 13.0.0: Thu 
> Sep 19 22:22:27 PDT 2013; root:xnu-2422.1.72~6/REL\
> EASE_X86_64 x86_64
> Machine Type: i386-apple-darwin13.0.0
> 
> Bash Version: 4.2
> Patch Level: 45
> Release Status: release
> 
> Description:
> 
> An unquoted parameter expansion in a here string does not seem to 
> conform with my understanding of how
> read works with a local IFS override. Personally observed in bash 
> 3.2.51, 4.1.2 as well. I first learned
> of this possible bug via http://stackoverflow.com/q/20144593/1126841.
> 
> Repeat-By:
> $ var="hello:world"
> 
> # Case (1) I would expect "hello:world" in var1 if $var isn't split, 
> or "hello"
> # if it is. World splitting seems to occur after var1 is set, which 
> doesn't
> # seem to make sense.
> $ IFS=: read var1 var2 <<< $var
> $ echo "$var1"
> hello world
> 
> $var is split on : and the expansion results in "hello world" which doesn't 
> contains a :, so var1 gets "hello world"
> but yeah, this is a bit of a grey zone
>  

Looking at the change log at http://tiswww.case.edu/php/chet/bash/CHANGES, I 
noticed item (jj) in the changes to bash 4.1 alpha:

jj. Fixed a bug that caused variable expansion in here documents to look in
any temporary environment.

And I can observe that between bash 3.2 and bash 4.1:

bash-3.2 $ FOO=foo; FOO=bar cat <<< "$FOO"
bar

bash-4.1 $ FOO=foo; FOO=bar cat <<< "$FOO"
foo


However, why is the new value of IFS applied to the expansion of $var, instead 
of the current? Shouldn't read get the literal string "hello:world" from the 
here string? And if $var is split, why doesn't this expression work the same as

$ read var1 var2 <<< hello world

which is equivalent to

$ read var1 var2 world <<< hello

The following works as expected, which implies that the new value of IFS is 
being applied prematurely, but the quotes protect the colon from causing 
splitting and being removed until "hello:world" can be properly split inside 
the read builtin.

$ IFS=: read var1 var2 <<< "$var"


Documentation for declare/typeset does not address +=

2014-02-24 Thread Clint Hepner
Configuration Information [Automatically generated, do not change]:
Machine: i386
OS: darwin13.0.0
Compiler: clang
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='i386'
-DCONF_OSTYPE='darwin13.0.0' -DCONF_MACHTYPE='i386-apple-darwin13.0.0'
-DCONF_VENDOR='apple'
-DLOCALEDIR='/usr/local/Cellar/bash/4.2.45/share/locale' -DPACKAGE='bash'
-DSHELL -DHAVE_CONFIG_H -DMACOSX   -I.  -I. -I./include -I./lib
-I./lib/intl -I/private/tmp/bash-4vKN/bash-4.2/lib/intl  -DSSH_SOURCE_BASHRC
uname output: Darwin patikoija.local 13.0.0 Darwin Kernel Version 13.0.0:
Thu Sep 19 22:22:27 PDT 2013; root:xnu-2422.1.72~6/RELEASE_X86_64 x86_64
Machine Type: i386-apple-darwin13.0.0

Bash Version: 4.2
Patch Level: 45
Release Status: release

Description:
   The following code appears to work as expected:

   array=(a b c)
   a=array
   declare "$a+=(d)
   # array is now (a b c d)

   I assume this is intentional and in keeping with how += works, but
the entry for
   declare/typeset in the man page only addresses the case where the
variable name
   is followed by =value.


Fix:
Mention += in the entry for declare/typeset, or otherwise clarify
how the builtin works.


Re: Spaces trimmed from $* when assigned while IFS is unset [was: Unexpected word splitting on $* ...]

2017-09-27 Thread Clint Hepner
On Wed, Sep 27, 2017 at 9:10 AM, Martijn Dekker  wrote:

> Op 27-09-17 om 14:44 schreef Greg Wooledge:
> > I'm just going to chalk this up as yet another example of unquoted $*
> > or $@ being Completely Wrong.
>
> Nonsense. This is a bug in bash and it should be fixed, not excused.
> Quoting expansions should never be necessary for assignments.


For what its worth, this behavior appears to have been introduced in bash
4.3:

% cat tmp.bash
set "  abc  " " def  ghi " "jkl "
unset -v IFS var
var=${var-$*}/${var-$*}
printf '[%s]\n' "$var"
% for tag in 3.2 4.0 4.1 4.2 4.3 4.4; do echo "$tag"; docker run -i
bash:$tag bash < tmp.bash; done
3.2
[  abcdef  ghi  jkl /  abcdef  ghi  jkl ]
4.0
[  abcdef  ghi  jkl /  abcdef  ghi  jkl ]
4.1
[  abcdef  ghi  jkl /  abcdef  ghi  jkl ]
4.2
[  abcdef  ghi  jkl /  abcdef  ghi  jkl ]
4.3
[abc def ghi jkl/abc def ghi jkl]
4.4
[abc def ghi jkl/abc def ghi jkl]


Re: Enabling History Expansion with `set -H'.

2018-01-21 Thread Clint Hepner

> On 2018 Jan 21 , at 7:13 a, Ralph Corderoy  wrote:
> 
> Hi,
> 
> Please keep me CC'd.
> 
> bash package 4.4.012-2 on Arch Linux,
> `version 4.4.12(1)-release (x86_64-unknown-linux-gnu)'.
> 
> I'm trying to enable history expansion in a non-interactive bash with
> `set -H'.
> 
>$ printf '%s\n' ': foo' 'echo !!' 'set -H' ': bar' 'echo !!' |
>> bash 
>!!
>!!
>$
> 
> I'd expect the second `!!' to be `: bar'.
> What am I misunderstanding?

You enabled history *expansion*, but not the history mechanism itself, so there 
is nothing for !! to expand to. You need `set -o history` as well.

$ printf '%s\n' ': foo' 'echo !!' 'set -H -o history' ': bar' 'echo !!' | 
bash
!!
echo : bar
: bar

The second line, 'echo : bar', is the result of the expansion itself, prior to 
the resulting command actually being executed.



Re: Unset array doesn't work

2018-02-26 Thread Clint Hepner

> On 2018 Feb 26 , at 4:31 a, Robert Elz  wrote:
> 
>Date:Mon, 12 Feb 2018 09:26:37 -0500
>From:Chet Ramey 
>Message-ID:  <790ade74-690f-541c-9ab4-635991744...@case.edu>
> 
>  | This is bash's dynamic scoping. The visibility of a local variable is
>  | restricted to a function and its children, and `unset' removes the
>  | currently-visible instance. Removing such an instance can `unconver' an
>  | instance in a previous scope.
> 
> Frankly this is brain dead, unset should not be unlocal (or something equiv)
> 
> eg: if I have a func
> 
>   myfunc() {
>   local IFS
>   unset IFS
>   # do some code
>   }
> 
> the very last thing that I want is for the global IFS to apply.
> 
> The intent is to use the default IFS value, which is what an unset IFS
> produces, without affecting the current global IFS setting.

As you say, the intent is to use a particular value of the variable. The fact 
that unsetting
IFS causes it to use a default value other than an empty string seems more like 
a concession
to historical usage than a feature that should be explicitly used. If you need 
a particular
value, assign it instead of using a nonobvious alternative that is only shorter 
by three of characters:

IFS=$' \t\n'
unset IFS

> In this example, I could do IFS=$' \t\n' if I was willing to assume that 
> $'...'
> support exists (the shell executing the script is not necessarily going to
> be bash)

You are already assuming $'...'-support if you are using local; both are bash 
extensions
to the POSIX standard.

If portability is your goal, making a nonstandard change to one shell isn't 
going to help. Suppose
bash did change the behavior of unset (even optionally) or added an "unlocal" 
command, and you
made use of this. Now your script is limited to bash 4.5 or newer, and *maybe* 
any other shell that
could be convinced to implement something similar. $'...' already enjoys wider 
level of support.

> or I could do
> 
>   IFS='   
> '
> 
> and just hope that survives as written (it would straight from the editor,
> but who knows when someone else decides that trailing whitespace on
> lines should all be deleted).   Variants to avoid that get even uglier.

People who remove whitespace from inside quotes do so at their own risk. Not all
trailing whitespace is extraneous.

If necessary, you can define a global (at the expense of a single subprocess)

myIFS=$(printf ' \t\n')

to get a value in a completely POSIX-compatible way you can use to assign to a 
localized
copy of IFS. (But I want to reiterate that you have already thrown POSIX 
compatibility out
the window by using local in the first place, so you might as well use $' 
\t\n'.)

-- 
Clint


Re: bash long prompt, color going past the end of prompt after reaching bottom of terminal

2018-03-23 Thread Clint Hepner

> On 2018 Mar 23 , at 8:26 a, Greg Wooledge  wrote:
> 
> On Fri, Mar 23, 2018 at 12:36:22AM +0200, Ilkka Virta wrote:
>> I get the same with '4.4.12(1)-release' too, but it doesn't seem related to
>> Bash or the prompt. I can get it with just a printf, the colored part just
>> needs to get wrapped by the end of line.
>> 
>> printf "%100s $(tput setab 1)colored part$(tput sgr0) normal again\n"
>> 
>> If the screen scrolls, the background color on the last character gets
>> copied to the next line.
> 
> Ahh.  In that case, it's a bug (or undesired feature) of your terminal
> emulator, and you should address the bug reports in that direction.
> 

I can reproduce buggy appearance in the following, all running on macOS:
 * iTerm2
 * Terminal
 * The console of a CentOS 7 VM running in Virtual Box

Adapting the original function to work with zsh,

# Changes:
# \w -> %~
# \[...\] -> %{...%}
# \$ -> %#
calculate_prompt1()
{
host="my-linux"
git_branch="a very very very very very very very very very very very very 
very very long prompt"
prompt="@$host %~ : %{$(tput bold)$(tput setab 1)$(tput setaf 
7)%}${git_branch}%{$(tput sgr0)%}%# "
export PS1="$prompt"
}

I cannot reproduce in any of the three environments listed above.

Clint




Re: Number with sign is read as octal despite a leading 10#

2018-07-09 Thread Clint Hepner
The + is a unary operator, not part of the literal. Write $((+10#0034)) instead.

--
Clint
On Jul 9, 2018, 9:24 PM -0400, Isaac Marcos , 
wrote:
> Configuration Information [Automatically generated, do not change]:
> Machine: x86_64
> OS: linux-gnu
> Compiler: gcc
> Compilation CFLAGS: -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64'
> -DCONF_OSTYPE='linux-gnu' -DCONF_MACHTYPE='x86_64-pc-linux-gnu'
> -DCONF_VENDOR
> uname output: Linux IO 4.9.0-6-amd64 #1 SMP Debian 4.9.88-1+deb9u1
> (2018-05-07) x86_64 GNU/Linux
> Machine Type: x86_64-pc-linux-gnu
>
> Bash Version: 4.4
> Patch Level: 12
> Release Status: release
>
> Description:
> A value inside an arithmetic expansion is processed as octal despite using
> a 10# preffix.
>
> Repeat-By:
> $ echo $((10#+0034))
> 28
>
> Fix:
> Extract optional sign before parsing the number, re-attach after.
>
> --
> Cases are always threesome:
> Best case, Worst case, and Just in case


Re: [1] 69728 segmentation fault bash

2018-07-20 Thread Clint Hepner


> On 2018 Jul 20 , at 9:27 a, Mr Guiguilebreton  wrote:
> 
> Hello, check this command in GNU bash, version 3.2.57(1)-release
> (x86_64-apple-darwin17):
> 
> ls () { ls -lG;}; ls

You wrote a recursive function with no base case. Don't do that.

ls () { command ls -lG; }; ls

or use an alias for one of its few legitimate use cases

alias ls='ls -lG'



Re: [1] 69728 segmentation fault bash

2018-07-20 Thread Clint Hepner


> On 2018 Jul 20 , at 10:40 a, Mr Guiguilebreton  wrote:
> 
> Yes, i now. I test the syntax and the parse error because I programming a 
> command interpreter bash in C language and I report the Segmentation Fault 
> for help you to debug. If you want I can help you free to solve the problem.

See https://lists.gnu.org/archive/html/bug-bash/2017-09/msg00048.html.

> 
> 
> freely,
> Guillaume Madec
> (+33)6 46 01 00 79
> 
> 2018-07-20 16:17 GMT+02:00 Clint Hepner :
> 
> > On 2018 Jul 20 , at 9:27 a, Mr Guiguilebreton  wrote:
> > 
> > Hello, check this command in GNU bash, version 3.2.57(1)-release
> > (x86_64-apple-darwin17):
> > 
> > ls () { ls -lG;}; ls
> 
> You wrote a recursive function with no base case. Don't do that.
> 
> ls () { command ls -lG; }; ls
> 
> or use an alias for one of its few legitimate use cases
> 
> alias ls='ls -lG'
> 




Tilde expansion in assignment-like context

2018-08-06 Thread Clint Hepner
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: darwin16.7.0
Compiler: clang
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' -DCONF_OSTYPE='d\
arwin16.7.0' -DCONF_MACHTYPE='x86_64-apple-darwin16.7.0' -DCONF_VENDOR='apple' \
-DLOCALEDIR='/usr/local/Cellar/bash/4.4.19/share/locale' -DPACKAGE='bash' -DSHE\
LL -DHAVE_CONFIG_H -DMACOSX   -I.  -I. -I./include -I./lib -I./lib/intl -I/priv\
ate/tmp/bash-20180209-55597-111ek7c/bash-4.4/lib/intl  -DSSH_SOURCE_BASHRC -Wno\
-parentheses -Wno-format-security
uname output: Darwin hemma.local 16.7.0 Darwin Kernel Version 16.7.0: Thu Jun 2\
1 20:07:39 PDT 2018; root:xnu-3789.73.14~1/RELEASE_X86_64 x86_64
Machine Type: x86_64-apple-darwin16.7.0

Bash Version: 4.4
Patch Level: 19
Release Status: release

Description:
A non-initial unquoted tilde is expanded outside of an assignment. This
was raised as a question on Stack Overflow, 
https://stackoverflow.com/q/51713759/1126841.

Repeat-By:

$ set +k
$ echo home_dir=~
home_dir=/Users/chepner

A similar string that does not start with a valid identifier leaves the tilde 
unexpanded.

$ echo --home_dir=~
--home_dir=~

The behavior is also present in commit 
057a9fbdb4d9ad01b000743fcea9918b80823afc, bash-20180803 snapshot.


Fix:
[Description of how to fix the problem.  If you don't know a
fix for the problem, don't include this section.]


Re: Tilde expansion in assignment-like context

2018-08-06 Thread Clint Hepner


> On 2018 Aug 6 , at 3:45 p, Chet Ramey  wrote:
> 
> On 8/6/18 3:09 PM, Clint Hepner wrote:
> 
>> Bash Version: 4.4
>> Patch Level: 19
>> Release Status: release
>> 
>> Description:
>>A non-initial unquoted tilde is expanded outside of an assignment. 
>> This
>>was raised as a question on Stack Overflow, 
>> https://stackoverflow.com/q/51713759/1126841.
>> 
>> Repeat-By:
>> 
>>$ set +k
>>$ echo home_dir=~
>>home_dir=/Users/chepner
> 
> Yes. Bash has done this since its earliest days. A word that looks like an
> assignment statement has tilde expansion performed after unquoted =~ and :~
> no matter where it appears on the command line. This makes things like
> 
>   make DESTDIR=~stager/bash-install
> or
>   export PATH=/usr/local/bin:~/bin:/usr/bin
> 
> easy and convenient.

Oh, right. For some reason, I had it in my head that this was only intended
for builtins like export, and that their status as builtins somehow made
the argument be treated as an assignment. I hadn't thought at all about 
non-builtin
commands like make.

> 
> The first version I can find that implemented the =~ and :~ tilde expansion
> prefixes is bash-1.10 (1991). Those early versions would have expanded
> something like `--home_dir=~'. The first version that restricted it to
> words that satisfied the assignment statement restrictions is bash-2.0
> (1996).
> 
> Bash doesn't do this when it's in posix mode. The first version that
> implemented that was bash-1.14.0.
> 
> -- 
> ``The lyf so short, the craft so long to lerne.'' - Chaucer
>``Ars longa, vita brevis'' - Hippocrates
> Chet Ramey, UTech, CWRUc...@case.eduhttp://tiswww.cwru.edu/~chet/




Re: Add sleep builtin

2018-08-19 Thread Clint Hepner


> On Aug 19, 2018, at 10:25 AM, konsolebox  wrote:
> 
> Hi Chet,
> 
> The sleep command is often used in loops and using the external sleep
> is expensive.  

Expensive is relative, as the time spent actually sleeping probably dwarfs the 
startup time. If not, you probably want to find an alternative to polling 
anyway.

Clint


Re: x[

2019-07-29 Thread Clint Hepner



> On 2019 Jul 29 , at 12:55 p, Isabella Bosia  wrote:
> 
> haven't really looked into why this happens but x[ seems to trigger some
> funny parser behavior
> 
> x[ newline should not prompt with PS2
> 
> it can't be defined as a normal sh function, but it can be defined with the
> function keyword
> 
> it can't be called like a normal function, but things like "x[" or \x[ work
> 
> this bug seems old


The ``[`` begins a valid shell pattern, so the parser continues to accept input 
until the closing ``]`` is found. Pathname expansion (apparently) does not 
apply to the first "argument" of the ``function`` command.


Re: [FR] save command times and exit status in history automatically

2019-11-07 Thread Clint Hepner



> On 2019 Nov 7 , at 3:18 p, Daniel Colascione  wrote:
> 
> On Thu, Nov 7, 2019 at 12:09 PM Chet Ramey  wrote:
>> 
>> On 11/5/19 12:49 PM, Daniel Colascione wrote:
>>> Right now, bash history saves only the command line actually executed.
>> 
>> This isn't quite the case. What it saves is the line returned from
>> readline, before it's expanded or executed.
> 
> Fair enough.
> 
>>> Why not also, optionally, save command execution times and exit
>>> statuses? This information is practically free to collect.
>> 
>> Because by the time you gather this information, the command has already
>> been saved completely.
>> 
>> There have been various proposals to extend the timestamp with additional
>> information, but it's all data you can gather when the timestamp is saved
>> before the command is executed.
> 
> That's how history works today, yes. I'm wondering whether it'd be
> possible to maintain an auxiliary history that included not only the
> command lines read, but also their execution time and outcome. Doing
> something in PROMPT_COMMAND doesn't seem quite accurate. Maybe what I
> really want is something like $?, but instead of containing exit
> status, it would contain information from a struct rusage (derived
> from wait4) for the last command. Or something like that anyway. The
> larger point is that the shell could gather this information
> proactively almost for free and I don't think user code running in
> existing shell extension points can do the same job.
> 

Conceptually, this is quite a leap. Right now, the history list doesn't
require *any* effort beyond logging the input. What you are suggesting
may be readily accessible, but it's still *additional* work that must be
done.

Furthermore, a few issues off the top of my head:

* How would handle background jobs? Would they appear in the order they
are started, or the order they are completed?

* Suppose I start a loop like

   for x in 1 2 3; do
 someCommand "$x"
   done

  Do you want to store the result of the for loop? Each of the commands run
  in the loop? What would that look like?

* Would you want some way of linking the result of a `wait -n` command with
  the command it waited for? What would that look like?

* Would you want to store *any* output from a command in your log?

I think the design of such a feature would require a lot of careful thought
to be useful.

--
Clint




Re: man bash does not list 'in' as a builtin command

2019-11-25 Thread Clint Hepner



> On 2019 Nov 25 , at 4:43 p, Peter Benjamin  wrote:
> 
> 
> Description:
> 'in' is a builtin command and is not listed in the man page as such.
> 
> Repeat-By:
> 
> type at the bash command line:
> 
> $ in
> bash: syntax error near unexpected token `in'

This should be a big hint that it is *not* a built-in command. If it
were, you would have run the command, not gotten a syntax error.

> 
> Why is this bug report important?  Why change the man page?  I wasted
> 20 minutes of my time, to prove to my satisfaction that 'in' was not
> invoking my script at all.  Search engines did not find a match to the
> error message.  I can not imagine this report is the first time this
> bug was found.

Given that ``in'' *is* documented as a reserved word

RESERVED WORDS
   Reserved words are words that have a special meaning to the shell.  
The
   following words are recognized as reserved when unquoted and either 
the
   first word of a simple command (see SHELL GRAMMAR below) or  the  
third
   word of a case or for command:

   !  case   coproc   do  done elif else esac fi for function if in 
select
   then until while { } time [[ ]]

the question becomes, what change to the man page do you think would have 
helped you 
find this more quickly?

One thing that comes to mind would be a short (though off-topic) entry in
the SHELL BUILTIN COMMANDS section, like

in
See the Compound Commands section under SHELL GRAMMMAR. Used
to form the ``case'', ``select'', and ``for'' commands.

I don't really like that idea, as it starts down a slippery slope for adding
all sorts of non-command entries, turning the section into a general glossary 
rather than
a listing of built-in commands.

Alternatively, maybe a short list of sections at the top of the man page would 
provide
a hint.

For example, imagine the man page started out like this:

NAME
bash - GNU Bourne-Again Shell

SYNOPSIS
bash [options] [command_string | file]

DESCRIPTION

Bash is [...]

TABLE OF CONTENTS

OPTIONS
ARGUMENTS
INVOCATION
DEFINITIONS
RESERVED WORDS
SHELL GRAMMAR
COMMENTS
QUOTING
PARAMETERS
EXPANSION
REDIRECTION
ALIASES
FUNCTIONS
ARITHMETIC EVALUATION
CONDITIONAL EXPRESSIONS
SIMPLE COMMAND EXPANSION
COMMAND EXECUTION
COMMAND EXECUTION ENVIRONMENT
ENVIRONMENT
EXIT STATUS
SIGNALS
JOB CONTROL
PROMPTING
READLINE
HISTORY
HISTORY EXPANSION
SHELL BUILTIN COMMANDS
RESTRICTED SHELL
SEE ALSO
FILES
AUTHORS
BUG REPORTS
BUGS

OPTIONS
   All of the single-character shell options ...

[etc]

The table of contents inserted between the existing DESCRIPTION and OPTIONS 
sections is relatively brief,
and both RESERVED WORDS and SHELL GRAMMAR seem like they would be good starting 
places to look for
information about the ``in'' token mentioned in the syntax error.

Given how short most of the section names are, it could easily be formatted as 
two columns, making it
easier to scan.



--
Clint


Re: Two states of empty arrays

2019-12-12 Thread Clint Hepner
On Thu, Dec 12, 2019 at 1:10 PM Léa Gris  wrote:

> Hello,
>
> Depending on how an empty array is declared, it is not stored with the
> same state.
>
> # Empty array declared without parenthesis
> unset myArr
> declare -a myArr
> typeset -p myArr
> echo "${#myArr[@]}"
>
> output:
> declare -a myArr
> 0
>

Here, you haven't yet defined a parameter named myArr; you have only set
the array
attribute on the name myArr. You can see something similar with other
attributes:

$ declare -i x
$ [[ -v x ]] || echo "x not defined"
x not defined
$ declare -p x
declare -i x


>
> # Empty array declared without parenthesis
> unset myArr
> declare -a myArr=()
> typeset -p myArr
> echo "${#myArr[@]}"
>
> output:
> declare -a myArr=()
> 0
>
>
With the assignment, you have an actual parameter named myArr. Continuing
the integer attribute
example from above,

$ x=3
$ declare -p x
declare -i x="3"
$ [[ -v x ]] || echo "x not defined"   # No output


--
Clint


read and inconsistent handling of trailing null field?

2020-01-29 Thread Clint Hepner
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: darwin19.2.0
Compiler: gcc
Compilation CFLAGS: -g -O2 -Wno-parentheses -Wno-format-security
uname output: Darwin hemma.local 19.2.0 Darwin Kernel Version 19.2.0: Sat Nov  
9 03:47:04 PST 2019; root:xnu-6153.61.1~20/RELEASE_X86_64 x86_64
Machine Type: x86_64-apple-darwin19.2.0

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

Description:

read seems to incorrectly drop a null field when performing word-splitting and 
more fields than variables.

All the examples below use

IFS== read -r n v

for some input of the form ``name=var...``


The relative bit of the POSIX spec concerns how to set the variables when there 
are fewer arguments
to read than there are fields.

• The field that corresponds to the last var in the normal assignment 
sequence described above

• The delimiter(s) that follow the field corresponding to the last var

• The remaining fields and their delimiters, with trailing IFS white 
space ignored

Repeat-By:


% ./bash
bash-5.0$ echo $BASH_VERSION
5.0.11(5)-release
bash-5.0$ IFS== read -r n v <<< "name=var="
bash-5.0$ echo "$v"
var

I would expect "var=" as the output, as the string is split into 3 fields (the 
last being empty).
(ksh and dash also drop the final null field, which is what makes me suspect I 
am missing a subtlety
of the POSIX spec. zsh seems to preserve the final =, though I did not dig into 
which options
I have set that might affect the result.)

Same result using here-document, so I don't think this is a here-string issue.

If the trailing null field is not the one to put the field count over the 
argument count, it
works as expected.

bash-5.0$ IFS== read -r n v <<< "name=var=f="
bash-5.0$ echo "$v"
var=f=
bash-5.0$ IFS== read -r n v <<< "name=var=="
bash-5.0$ echo "$value"
var==


Re: read and inconsistent handling of trailing null field?

2020-01-29 Thread Clint Hepner



> On 2020 Jan 29 , at 10:30 a, Chet Ramey  wrote:
> 
> On 1/29/20 10:19 AM, Clint Hepner wrote:
> 
>> Bash Version: 5.0
>> Patch Level: 11
>> Release Status: release
>> 
>> Description:
>> 
>> read seems to incorrectly drop a null field when performing word-splitting 
>> and more fields than variables.
>> 
>> All the examples below use
>> 
>>IFS== read -r n v
>> 
>> for some input of the form ``name=var...``
>> 
>> 
>> The relative bit of the POSIX spec concerns how to set the variables when 
>> there are fewer arguments
>> to read than there are fields.
> 
> There are exactly two variables and two (split) arguments.
> 
> "The shell shall treat each character of the IFS as a delimiter and use the
> delimiters as field terminators to split..."
> 
> https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html#tag_18_06_05
> 
> 

Ah, OK. So if I have

IFS=, read -r n v <<< "a,b,c,"

there are two variables and 3 split arguments: "a", "b", and "c". Then 
according to the
specification for read, "a" is assigned to n, and we assign to v as follows:

  1. first add the second field "b": v=b
  2. then the delimiter following "b": v=b,
  3. The remaining fields and their delimiters: first v=b,c then v=b,c,

So the final "," in the value of v isn't separating c and a mythical null 
field, but
is terminating the final field c.

Then

IFS=, read -r n v <<< "a,b,,"

has fields "a", "b", and "", and again v is assigned "b", ",", "", ",".

Thanks Chet and Greg (for pointing out 
https://mywiki.wooledge.org/BashPitfalls#pf47)

-- 
Clint


Inconsistent arithmetic evaluation of parameters

2015-09-01 Thread Clint Hepner
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: darwin14.5.0
Compiler: clang
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' 
-DCONF_OSTYPE='darwin14.5.0' -DCONF_MACHTYPE='x86_64-apple-darwin14.5.0' 
-DCONF_VENDOR='apple' -DLOCALEDIR='/usr/local/Cellar/bash/4.3.42/share/locale' 
-DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H -DMACOSX   -I.  -I. -I./include 
-I./lib -I./lib/intl -I/private/tmp/bash20150826-30526-beo5d/bash-4.3/lib/intl  
-DSSH_SOURCE_BASHRC
uname output: Darwin 192.168.1.17 14.5.0 Darwin Kernel Version 14.5.0: Wed Jul 
29 02:26:53 PDT 2015; root:xnu-2782.40.9~1/RELEASE_X86_64 x86_64
Machine Type: x86_64-apple-darwin14.5.0

Bash Version: 4.3
Patch Level: 42
Release Status: release

Description:

Parameter names are recursively evaluated in an arithmetic expression, but this
is not done consistently.

Repeat-By:

foo=bar
bar=5
echo $(( foo ))# produces 5
echo $(( foo++ ))  # produces 5
echo $foo  # produces 6, not bar
echo $bar  # produces 5, not 6


Fix:

It's not clear what should be fixed. First of all, it's not clear what foo
is actually evaluating to. If it evaluates to bar, then bar should be
incremented. If it evaluates to 5, then the autoincrement should be a syntax
error.

It seems like the "correct" behavior would be for a parameter to be evaluated
until its value is a parameter name whose value is an actual integer, such that

foo=bar
bar=baz
baz=5
echo $(( foo++ ))  # produces 5; result should be baz=6 and foo, bar 
unchanged.


Word-splitting with here document?

2015-09-02 Thread Clint Hepner
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: darwin13.4.0
Compiler: clang
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64'
-DCONF_OSTYPE='darwin13.4.0' -DCONF_MACHTYPE='x86_64-apple-darwin13.4.0'
-DCONF_VENDOR='apple'
-DLOCALEDIR='/usr/local/Cellar/bash/4.3.30/share/locale' -DPACKAGE='bash'
-DSHELL -DHAVE_CONFIG_H -DMACOSX   -I.  -I. -I./include -I./lib
-I./lib/intl -I/private/tmp/bash-tugB48/bash-4.3/lib/intl
 -DSSH_SOURCE_BASHRC
uname output: Darwin patikoija 14.4.0 Darwin Kernel Version 14.4.0: Thu May
28 11:35:04 PDT 2015; root:xnu-2782.30.5~1/RELEASE_X86_64 x86_64
Machine Type: x86_64-apple-darwin13.4.0

Bash Version: 4.3
Patch Level: 30
Release Status: release

Description:
   Unexpected word splitting in here string. According to the man page,
"Pathname  expansion and word splitting are not performed." This is
essentially the same wording used to explain how `[[...]]` treats its
contents, but the here string seems to behave differently.

Repeat-By:

   $ x="foobar"
   $ [[ $x == "foobar" ]]  # succeeds, no word splitting on
value of x
   $ cat <<< $x # Word-splitting appears to collapse the run of
whitespace
   foo bar
   $ cat <<< "$x"  # Whitespace preserved, as with here doc
   foo bar


Execution of code by ${...@P}

2016-11-14 Thread Clint Hepner
Configuration Information [Automatically generated, do not change]:
Machine: x86_64
OS: darwin16.0.0
Compiler: clang
Compilation CFLAGS:  -DPROGRAM='bash' -DCONF_HOSTTYPE='x86_64' 
-DCONF_OSTYPE='darwin16.0.0' -DCONF_MACHTYPE='x86_64-apple-darwin16.0.0' 
-DCONF_VENDOR='apple' -DLOCALEDIR='/usr/local/Cellar/bash/4.4_1/share/locale' 
-DPACKAGE='bash' -DSHELL -DHAVE_CONFIG_H -DMACOSX   -I.  -I. -I./include 
-I./lib -I./lib/intl 
-I/private/tmp/bash-20160928-76620-1cvsdye/bash-4.4/lib/intl  
-DSSH_SOURCE_BASHRC -Wno-parentheses -Wno-format-security
uname output: Darwin 192.168.1.21 16.1.0 Darwin Kernel Version 16.1.0: Thu Oct 
13 21:26:57 PDT 2016; root:xnu-3789.21.3~60/RELEASE_X86_64 x86_64
Machine Type: x86_64-apple-darwin16.0.0

Bash Version: 4.4
Patch Level: 0
Release Status: release

Description:

 ${...@P} expansion allows arbitrary code to run. This might
 be intentional, as it is how prompt strings work, but it
 does feel like an understated security risk.


Repeat-By:

 $ foo='$(echo hello)'
 $ echo "${foo}"
 $(echo hello)
 $ echo "${foo@P}"
 hello



Fix:
The man page might explicitly state that command substitutions
in the value of the expanded parameter will be executed.

This also suggests one or more additional operators that perform
things like parameter expansion, pathname expansions, etc.