Re: No expansions performed while declaring an associative array using a list of keys and values

2020-12-15 Thread Glenn Jackman
On 2020-12-11 11:41, Chet Ramey wrote:
> I agree that it would be useful to have
> 
> foo='1 2'
> declare -A v1=$( $foo 3 )
> declare -A v2=$( [$foo]=3 )
> 
> set the two arrays to the same contents

I would think that these pairs of invocations would correspond:

declare -A v1=$( $foo 3 )
declare -A v1=$( [1]=2 [3]="")

declare -A v1=$( "$foo" 3 )
declare -A v1=$( ['1 2']=3 )

Do word splitting and quote removal not occur within the parentheses of an
_associative_ array definition?

As the manual states:

> When assigning to an associative array, the words in a compound assignment
> may be either assignment statements, for which the subscript is required,
> or a list of words that is interpreted as a sequence of alternating keys
> and values: name=(key1 value1 key2 value2 … ). These are treated
> identically to name=( [key1]=value1 [key2]=value2 … ). 

They do not appear to be treated identically:

$ declare -A name=( [foo]=bar [baz]="hello world" )
$ declare -p name
declare -A name=([foo]="bar" [baz]="hello world" )

but with a key-value list, the quotes are preserved:

$ declare -A name=( foo bar baz "hello world" )
$ declare -p name
declare -A name=([foo]="bar" [baz]="\"hello world\"" )



I'd love to be able to read a key-value list from a CSV file, like

$ line="foo,bar,baz,hello world"
$ enable -f csv csv
$ csv "$line"
$ declare -A assoc
$ assoc=( "${CSV[@]}" )

But, as previously stated, the whole array is taken as a single key

$ declare -p assoc
declare -A assoc=(["foo bar baz hello world"]="" )

There's a workaround using `eval` and shell-quoted transformation, 
but ... yuck:

$ eval assoc=( "${CSV[@]@Q}" )
$ declare -p assoc
declare -A assoc=([foo]="bar" [baz]="hello world" )

Particularly when this same technique works for indexed arrays: this results in
a copy of the CSV array, not a new array with only a single element:

declare -a copy
copy=("${CSV[@]}")




-- 
Glenn Jackman
Write a wise saying and your name will live forever. -- Anonymous



Re: No expansions performed while declaring an associative array using a list of keys and values

2020-12-15 Thread Chet Ramey

On 12/15/20 11:23 AM, Glenn Jackman wrote:

On 2020-12-11 11:41, Chet Ramey wrote:

I agree that it would be useful to have

foo='1 2'
declare -A v1=$( $foo 3 )
declare -A v2=$( [$foo]=3 )

set the two arrays to the same contents


I would think that these pairs of invocations would correspond:

 declare -A v1=$( $foo 3 )
 declare -A v1=$( [1]=2 [3]="")

 declare -A v1=$( "$foo" 3 )
 declare -A v1=$( ['1 2']=3 )

Do word splitting and quote removal not occur within the parentheses of an
_associative_ array definition?


Associative array keys do not undergo word splitting on assignment, whether
they are used in a subscript or the alternate key-value synatx. This has
been the case since their introduction in bash-4.0.


As the manual states:


When assigning to an associative array, the words in a compound assignment
may be either assignment statements, for which the subscript is required,
or a list of words that is interpreted as a sequence of alternating keys
and values: name=(key1 value1 key2 value2 … ). These are treated
identically to name=( [key1]=value1 [key2]=value2 … ).


They do not appear to be treated identically:

 $ declare -A name=( [foo]=bar [baz]="hello world" )
 $ declare -p name
 declare -A name=([foo]="bar" [baz]="hello world" )

but with a key-value list, the quotes are preserved:

 $ declare -A name=( foo bar baz "hello world" )
 $ declare -p name
 declare -A name=([foo]="bar" [baz]="\"hello world\"" )


Yes, this is what I referred to in the message you quoted above.


I'd love to be able to read a key-value list from a CSV file, like

 $ line="foo,bar,baz,hello world"
 $ enable -f csv csv
 $ csv "$line"
 $ declare -A assoc
 $ assoc=( "${CSV[@]}" )


I understand that. I don't see a clean way to reconcile it with the 
restriction that keys don't undergo word splitting.





But, as previously stated, the whole array is taken as a single key

 $ declare -p assoc
 declare -A assoc=(["foo bar baz hello world"]="" )

There's a workaround using `eval` and shell-quoted transformation,
but ... yuck:

 $ eval assoc=( "${CSV[@]@Q}" )
 $ declare -p assoc
 declare -A assoc=([foo]="bar" [baz]="hello world" )


It is possible, if not quite as elegant as you'd like.


Particularly when this same technique works for indexed arrays: this results in
a copy of the CSV array, not a new array with only a single element:

 declare -a copy
 copy=("${CSV[@]}")


Yes, indexed arrays and associative array key-value pairs behave
differently. In particular, the keys don't appear in the above assignmnent
at all.

Chet

--
``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: Request: a command to do a return completely in normal, ie. not subshell

2020-12-15 Thread Dale R. Worley
Budi  writes:
> Can we have a command to do a return completely (as if it returns from
> main function) when it is being in a third nested function call, in
> order to get back to shell prompt at once, in normal, ie. not
> subshell?

You probably want to use the "exit" command, if all of this is in a
shell script.

Dale