[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [Help-bash] Expansions in associative array subscripts
From: |
Andy Chu |
Subject: |
Re: [Help-bash] Expansions in associative array subscripts |
Date: |
Wed, 7 Aug 2019 00:03:01 -0700 |
On Tue, Aug 6, 2019 at 6:08 PM David <address@hidden> wrote:
> I don't feel confident about what context the subscript of an *associative*
> array is evaluated/parsed in.
Here's one short answer: Run your script with my bash-compatible shell
Oil and see if it works: http://www.oilshell.org/
If it works under OSH, it should work under bash. But it will also
give you an error for hard-to-parse cases, which may make your code
clearer:
$ declare -A A
$ A[x]=1
A[x]=1
^~
[ interactive ]:5: fatal: Associative array keys must be strings: $x
'x' "$x" etc.
In other words, it's supposed to be a "sane" subset of bash semantics.
Also, parsing is not the only pitfall with indexed and associative
arrays. Another one is what happens when you mix -a and -A with
literals like (a b) and (['key']=value).
If the flag doesn't match the literal, the results can be very
confusing. Oil fixes this in a backward compatible way by
implementing a subset of bash semantics. But that subset can still do
everything you need.
It probably won't replace anyone's usage of bash yet, but you can use
it as a development aid, as I mention here:
http://www.oilshell.org/blog/2019/06/17.html#toc_3
----
A longer explanation of the parsing question is in this blog post:
Parsing Bash is Undecidable: http://www.oilshell.org/blog/2016/10/20.html
"Undecidable" is a mathematical way of saying that parsing in bash
depends on the *runtime* types of variables, which is not how most
programming languages work. Some things in bash are parsed statically
like pipelines, for loops, if, functions, etc. But some things are
parsed dynamically, after variables are expanded/evaluated, which can
be confusing.
Both of these are OK, and are identical:
$ A[$x]=1
$ A["$x"]=1
These are also OK, and identical:
$ declare -a a # indexed array
$ a[x]=1 # x is the name of a variable, not a string
$ a[$x]=1
$ a["$x"]=1
The way Oil works is that what's between [] is always PARSED the same,
whether it's indexed or associative, unlike in bash. But they are
EVALUATED differently.
- With indexed arrays, the index is evaluated and coerced to an INTEGER.
- With associative arrays, it's evaluated to a STRING.
This is both compatible with bash and closer to what you would expect
if you've used a language like Python, JavaScript, Ruby, Perl, etc.
-----
If you find any case with regard to arrays that works in OSH but
doesn't work in bash, I'd be interested in knowing about it.
https://github.com/oilshell/oil/issues
I believe OSH has pretty simple and understandable semantics, and a
lot of the questions can be answered by trying it, because it will
give a clear error message if it doesn't work.
For example, there is no pathname/glob expansion in array indexes.
I'm pretty sure bash doesn't do it either.
I didn't read the section you quoted carefully, but maybe it is
talking about something like this:
a=('*.py') # note the quotes
$ echo ${a[@]}
__init__.py
$ echo "${a[@]}"
*.py
which has to do with arrays, but not array INDICES. Personally I
always use "$@" and "${a[@]}" and never the other forms.
You may also be interested in this blog post:
Thirteen Incorrect Ways and Two Awkward Ways to Use Arrays --
http://www.oilshell.org/blog/2016/11/06.html
Basically that is addressing the "!QEFS problem". I'm introducing a
few new features to OSH right now that make it easier to manipulate
arrays. For example, splicing is just
@a (2 characters)
and not
"${a[@]}" (8 characters)
if you enable 'shopt -s oil-parse-at'.
Andy