Re: Issue declaring an array via a variable name

2021-08-19 Thread Oğuz
20 Ağustos 2021 Cuma tarihinde Hunter Wittenborn <
hun...@hunterwittenborn.com> yazdı:
>
> So, in my opinion, this should logically work (from the view of an end
> user):
>
>
>
> declare "var"=("i" "j")
>

`"var"=("i" "j")' doesn't qualify as an assignment statement as the
variable name is quoted. As an end user I would expect the unquoted `('
operator to cause a syntax error, just as it does in `echo ('.


-- 
Oğuz


Re: Issue declaring an array via a variable name

2021-08-19 Thread Hunter Wittenborn
The
 general consensus seems to be that this isn't really a bug (from what 
I've understood), but it looks like I can use a variable reference to 
solve the issue nevertheless.



Regardless, 
I'm still wanting to almost classify this as a bug (or possibly a 
feature request; it feels like it's getting blurry where it would be at 
this point).







Because; Both of these work:



declare "var"="i"

declare var=("i" "j")



So, in my opinion, this should logically work (from the view of an end user):



declare "var"=("i" "j")





The same issue applies for variables, though seeming to not matter if they're 
in quotes or not for those.



Lastly
 - again, the variable reference issue is seeming to work fairly fine 
for my current use cases. I just don't really want to throw this off as a
 "syntax error" when this quite arguably seems like a bug instead.





 On Mon, 16 Aug 2021 09:27:55 -0500 Greg Wooledge  wrote 



On Mon, Aug 16, 2021 at 04:10:31PM +0200, Alex fxmbsw7 Ratchev wrote: 
> i dunno but, i had many testings many times 
> the stable wanted is to enclose the per arg definition in quotes, not like 
> "var"="var" 
> the right dash options is also useful 
 
I don't understand this paragraph at all. 
 
> test=( a b ) t=var 
> declare -ga "$t=( ${test@Q} )" 
 
I believe this is what you're trying to show us: 
 
unicorn:~$ declare -ga "${t}=( ${test@Q} )" 
unicorn:~$ declare -ga "${t}"=( ${test@Q} ) 
bash: syntax error near unexpected token `(' 
 
And likewise, 
 
unicorn:~$ declare -ga "$t=( ${test@Q} )" 
unicorn:~$ declare -ga "$t"=( ${test@Q} ) 
bash: syntax error near unexpected token `(' 
 
There is something subtle happening there, at the parsing level.  Chet's 
explanation (quoted below) may suffice for some. 
 
For my own purposes, "if it hurts, don't do that" is good enough. 
But that's just me. 
 
> the same style i found secure and data preserving such alike: 
> "list=( $( ls -Ac --quoting-style=shell-escape ) )" 
 
That has nothing to do with the issue that started this thread.  You've 
got a plain old compound array assignment, with a command substitution 
inside it.  The variable on the left hand side ("list") is a valid 
shell identifier.  There are no surprises here. 
 
> On Mon, Aug 16, 2021, 15:57 Chet Ramey  wrote: 
> > It's a syntax error. There is an unquoted operator (`(') where the grammar 
> > does not allow it. 
> > 
> > `declare' does allow compound array assignment statements as arguments, and 
> > the parser accommodates this as long as two conditions hold: the parser can 
> > detect that the first word of a simple command is `declare' and the 
> > argument is a valid assignment statement. In this case, the second fails, 
> > since `"${variable}"' is not a valid shell identifier. That renders the 
> > argument not a valid assignment statement. 
 





---

Hunter Wittenborn

https://www.hunterwittenborn.com

https://github.com/hwittenborn


Re: EPOCHREALTIME

2021-08-19 Thread Eli Schwartz
On 8/19/21 12:18 PM, Léa Gris wrote:
> Le 19/08/2021 à 16:41, Eli Schwartz écrivait :
>> On 8/19/21 9:41 AM, Léa Gris wrote:
> 
> 
>> The error occurs, one would imagine, during the "convert string to
>> float" stage, after parsing argv or forking to bc or whatever, but
>> *before* passing it as an argument to printf(3). Here, bash is just
>> doing good error checking -- if you used
>> strtof("3.14159265358979323844", NULL) under a fr_FR.UTF-8 locale, it
>> would silently drop everything after the ".", and you would
>> "successfully" print 3,, but bash reports an error message.
> 
> A programming language shall distinguish between display format and data
> format.
> 
> Locale settings are for display format and shall not interfere with
> arguments parsing which is data format, or it create such data
> portability issues.


Whether you are right or wrong is a matter which I'm sublimely
indifferent to.

You seem to have missed the point of my statement, which is that this is
not about bash at all, and if you have an issue here, you should take it
up with the standards body.

The strtof() function of the C programming language is violating your
directive.


> This is exactly how I read the note from the POSIX documentation:
> 
> https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html#tag_20_09_16
> 
> 
>>   The bc utility always uses the  ( '.' ) character to represent
>>   a radix point, regardless of any decimal-point character specified as
>>   part of the current locale. In languages like C or awk, the 
>>   character is used in program source, so it can be portable and
>>   unambiguous, while the locale-specific character is used in input and
>>   output. Because there is no distinction between source and input in
>>   bc, this arrangement would not be possible. Using the locale-specific
>>   character in bc's input would introduce ambiguities into the language
> 
> Especially:
> 
> 
>> In languages like C or awk, the  character is used in program
>> source, so it can be portable and unambiguous


I challenge your reading of the POSIX documentation. The important part
is this:

> Because of such ambiguities, the  character is used in input.
> Having input follow different conventions from output would be
> confusing in either pipeline usage or interactive usage, so the
>  is also used in output.

POSIX acknowledges that using a comma in the output would be "correct
and follow our own rules, but since it's confusing we won't do it".


POSIX does NOT have similar logic in the documentation for printf, which
*mandates*

> The argument operands shall be treated as strings if the corresponding
> conversion specifier is b, c, or s, and shall be evaluated as if by
> the strtod() function if the corresponding conversion specifier is a,
> A, e, E, f, F, g, or G. Otherwise, they shall be evaluated as
> unsuffixed C integer constants, as described by the ISO C standard,
> with the following extensions:

and, indeed, strtof / strtod("3.14159265358979323844", NULL) in a French
locale is, as I originally explained, going to inherently follow
LC_NUMERIC no matter how silly you might think that is, because that's
how strtod/strtof work.

And you cannot pass a preprocessed float/double to the printf builtin,
because you don't have types, and therefore POSIX specifies how to
interpret it starting from a string.


> printf arguments are program source even if argument comes from a variable.
> 
> All things considered, if you are using floating-point numbers in a
> shell script, you are clearly not using the right tool for the job, but
> sometimes options are limited or not under your control.
> 
> Having a feature implemented in such a way, *that it cannot be used
> reliably or requires heavy work-around* (especially if you both need to
> process floating-point data in a portable format, and display in locale
> format)… is just calling for frustration and sorry errors:
> 
> For the record:
> 
> ash -c 'LC_ALL=fr_FR.utf8; printf "Pi: %2.4f\\n" "$(echo "4*a(1)" | bc
> -l)"'
> Pi: 3.1416
> 
> bash -c 'LC_ALL=fr_FR.utf8; printf "Pi: %2.4f\\n" "$(echo "4*a(1)" | bc
> -l)"'
> bash: line 1: printf: 3.14159265358979323844: invalid number
> Pi: 3,
> 
> dash -c 'LC_ALL=fr_FR.utf8; printf "Pi: %2.4f\\n" "$(echo "4*a(1)" | bc
> -l)"'
> Pi: 3.1416
> 
> ksh -c 'LC_ALL=fr_FR.utf8; printf "Pi: %2.4f\\n" "$(echo "4*a(1)" | bc
> -l)"'
> Pi: ksh: printf: 3.14159265358979323844: arithmetic syntax error
> ksh: printf: 3.14159265358979323844: arithmetic syntax error
> ksh: printf: warning: invalid argument of type f
> 3,
> 
> mksh -c 'LC_ALL=fr_FR.utf8; printf "Pi: %2.4f\\n" "$(echo "4*a(1)" | bc
> -l)"'
> Pi: 3,1416
> 
> zsh -c 'LC_ALL=fr_FR.utf8; printf "Pi: %2.4f\\n" "$(echo "4*a(1)" | bc
> -l)"'
> Pi: 3,1416


So you are saying only bash and ksh are POSIX-conformant. Okay, I
believe you. Would you like to report the POSIX conformance bug reports
to ash, dash, mksh, and zsh?

ash and dash have the additional 

Re: EPOCHREALTIME

2021-08-19 Thread Greg Wooledge
On Thu, Aug 19, 2021 at 06:18:46PM +0200, Léa Gris wrote:
> printf arguments are program source even if argument comes from a variable.

I don't agree with this.  I'd say that the *first* argument of printf
is part of the program source code, and any additional arguments given
are typically data, but *could* be source code in special cases.

printf '%s\n' "$var"

The above is the typical use of printf.  The first argument is crafted
by the programmer, and the remaining argument(s) are data fed to the
printf command as input.

Below, a less common use of printf, where all but one of the additional
arguments should be considered source code:

printf '%s\n' H 1i "$1" . w | ed -s "$2"

This is taken from .  The
argument in the middle, "$1", is clearly data.

> All things considered, if you are using floating-point numbers in a shell
> script, you are clearly not using the right tool for the job, but sometimes
> options are limited or not under your control.

Mostly true.  Using the shell's printf to round/format the display of a
floating-point number is acceptable, but it's right on the margin.

> Having a feature implemented in such a way, *that it cannot be used reliably
> or requires heavy work-around* (especially if you both need to process
> floating-point data in a portable format, and display in locale format)… is
> just calling for frustration and sorry errors:

You've just described almost every aspect of shell scripting.



Re: EPOCHREALTIME

2021-08-19 Thread Léa Gris

Le 19/08/2021 à 16:41, Eli Schwartz écrivait :

On 8/19/21 9:41 AM, Léa Gris wrote:




The error occurs, one would imagine, during the "convert string to
float" stage, after parsing argv or forking to bc or whatever, but
*before* passing it as an argument to printf(3). Here, bash is just
doing good error checking -- if you used
strtof("3.14159265358979323844", NULL) under a fr_FR.UTF-8 locale, it
would silently drop everything after the ".", and you would
"successfully" print 3,, but bash reports an error message.


A programming language shall distinguish between display format and data 
format.


Locale settings are for display format and shall not interfere with 
arguments parsing which is data format, or it create such data 
portability issues.


This is exactly how I read the note from the POSIX documentation:

https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html#tag_20_09_16


  The bc utility always uses the  ( '.' ) character to represent
  a radix point, regardless of any decimal-point character specified as
  part of the current locale. In languages like C or awk, the 
  character is used in program source, so it can be portable and
  unambiguous, while the locale-specific character is used in input and
  output. Because there is no distinction between source and input in
  bc, this arrangement would not be possible. Using the locale-specific
  character in bc's input would introduce ambiguities into the language


Especially:



In languages like C or awk, the  character is used in program source, 
so it can be portable and unambiguous


printf arguments are program source even if argument comes from a variable.

All things considered, if you are using floating-point numbers in a 
shell script, you are clearly not using the right tool for the job, but 
sometimes options are limited or not under your control.


Having a feature implemented in such a way, *that it cannot be used 
reliably or requires heavy work-around* (especially if you both need to 
process floating-point data in a portable format, and display in locale 
format)… is just calling for frustration and sorry errors:


For the record:

ash -c 'LC_ALL=fr_FR.utf8; printf "Pi: %2.4f\\n" "$(echo "4*a(1)" | bc -l)"'
Pi: 3.1416

bash -c 'LC_ALL=fr_FR.utf8; printf "Pi: %2.4f\\n" "$(echo "4*a(1)" | bc 
-l)"'

bash: line 1: printf: 3.14159265358979323844: invalid number
Pi: 3,

dash -c 'LC_ALL=fr_FR.utf8; printf "Pi: %2.4f\\n" "$(echo "4*a(1)" | bc 
-l)"'

Pi: 3.1416

ksh -c 'LC_ALL=fr_FR.utf8; printf "Pi: %2.4f\\n" "$(echo "4*a(1)" | bc -l)"'
Pi: ksh: printf: 3.14159265358979323844: arithmetic syntax error
ksh: printf: 3.14159265358979323844: arithmetic syntax error
ksh: printf: warning: invalid argument of type f
3,

mksh -c 'LC_ALL=fr_FR.utf8; printf "Pi: %2.4f\\n" "$(echo "4*a(1)" | bc 
-l)"'

Pi: 3,1416

zsh -c 'LC_ALL=fr_FR.utf8; printf "Pi: %2.4f\\n" "$(echo "4*a(1)" | bc -l)"'
Pi: 3,1416



--
Léa Gris




Re: EPOCHREALTIME

2021-08-19 Thread Greg Wooledge
On Thu, Aug 19, 2021 at 10:30:39AM -0400, Chet Ramey wrote:
> On 8/19/21 9:41 AM, Léa Gris wrote:
> > This will fail because of questionable design decision of having a mutable
> > argument format:
> > 
> > LC_NUMERIC=fr_FR@UTF-8; printf 'Pi: %2.4f\n` "$(bc -l <<<'4*a(1)')"
> > 
> > Note how the format indicator still use a dot, but the argument format's
> > decimal separator is that of the system's locale.
> 
> That's not a decimal point. The `2.4' is not some sort of decimal or
> floating point number. The dot just separates the field width from the
> precision.
> 
> If the argument is, in fact, a floating point number with a radix
> character, the radix character is appropriately locale-dependent.

What Chet said is correct, as far as it goes.  If you feed numbers like
"3,14159" to printf under a locale where "," is the radix character, it
works correctly.

The problem is that not all of the Unix/Linux tools are on the same page.

unicorn:~$ LC_NUMERIC=fr_FR.utf8 bash -c 'printf "Pi: %2.4f\n" "$(bc -l <<< 
"4*a(1)")"'
bash: line 1: printf: 3.14159265358979323844: invalid number
Pi: 3,

Despite the locale setting, bc(1) produced a number with "." as the
radix character, which bash's printf refused to acknowledge.

unicorn:~$ LC_NUMERIC=fr_FR.utf8 bc -l <<< '4*a(1)'
3.14159265358979323844

This is acknowledged in the POSIX documentation.
https://pubs.opengroup.org/onlinepubs/9699919799/utilities/bc.html#tag_20_09_16

  The bc utility always uses the  ( '.' ) character to represent
  a radix point, regardless of any decimal-point character specified as
  part of the current locale. In languages like C or awk, the 
  character is used in program source, so it can be portable and
  unambiguous, while the locale-specific character is used in input and
  output. Because there is no distinction between source and input in
  bc, this arrangement would not be possible. Using the locale-specific
  character in bc's input would introduce ambiguities into the language

So, it seems they did it on purpose.  I'm not sure what your best choice
would be, if you happen to be in a comma-as-radix part of the world.



Re: EPOCHREALTIME

2021-08-19 Thread Eli Schwartz
On 8/19/21 9:41 AM, Léa Gris wrote:
> Le 19/08/2021 à 15:10, hancooper écrivait :
>> Thusly, EPOCHREALTIME should not be made to depend on the locale.  I
>> have seen many
>> workarounds, that complicate rather than simplify something that
>> should be straighforward
>> and germaine to direct numeric computation.
> 
> A agree 100%
> 
> It is as frustrating as printf arguments format being dependent on
> locale settings:
> 
> This will fail because of questionable design decision of having a
> mutable argument format:
> 
> LC_NUMERIC=fr_FR@UTF-8; printf 'Pi: %2.4f\n` "$(bc -l <<<'4*a(1)')"
> 
> Note how the format indicator still use a dot, but the argument format's
> decimal separator is that of the system's locale.
> 
> Imagine if C++ or Java had methods with different signature depending on
> system locale. You would scream fool. But for Bash, it was decided it
> was all fine.


Bash printf behaves the same as C here (format indicator and all).

But without typed arguments it needs to parse the string
"3.14159265358979323844" into a float, because everything is a string
and thus doesn't have different signatures ever.

The error occurs, one would imagine, during the "convert string to
float" stage, after parsing argv or forking to bc or whatever, but
*before* passing it as an argument to printf(3). Here, bash is just
doing good error checking -- if you used
strtof("3.14159265358979323844", NULL) under a fr_FR.UTF-8 locale, it
would silently drop everything after the ".", and you would
"successfully" print 3,, but bash reports an error message.

Locales define output formatting for display, not source code formatting
for machine translation. Your entire problem, from beginning to end, has
nothing whatsoever to do with signatures, and everything to do with a
lack of types.

bc doesn't communicate a float-typed value to printf, but it also
doesn't respect LC_NUMERIC (for the reasons specified in the POSIX
description under "Application Usage").

On the other hand, printing the output of bc into a C source file and
compiling it, rather than interpreting it via strtof, would cause it to
be parsed as machine-formatted, not display-formatted, and hence the
LC_NUMERIC separator would not skew the results.

For a C program, because C has types and bash does not.


-- 
Eli Schwartz
Arch Linux Bug Wrangler and Trusted User



OpenPGP_signature
Description: OpenPGP digital signature


Re: EPOCHREALTIME

2021-08-19 Thread Chet Ramey
On 8/19/21 9:41 AM, Léa Gris wrote:

> This will fail because of questionable design decision of having a mutable
> argument format:
> 
> LC_NUMERIC=fr_FR@UTF-8; printf 'Pi: %2.4f\n` "$(bc -l <<<'4*a(1)')"
> 
> Note how the format indicator still use a dot, but the argument format's
> decimal separator is that of the system's locale.

That's not a decimal point. The `2.4' is not some sort of decimal or
floating point number. The dot just separates the field width from the
precision.

If the argument is, in fact, a floating point number with a radix
character, the radix character is appropriately locale-dependent.

-- 
``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: EPOCHREALTIME

2021-08-19 Thread Léa Gris

Le 19/08/2021 à 15:10, hancooper écrivait :

Thusly, EPOCHREALTIME should not be made to depend on the locale.  I have seen 
many
workarounds, that complicate rather than simplify something that should be 
straighforward
and germaine to direct numeric computation.


A agree 100%

It is as frustrating as printf arguments format being dependent on 
locale settings:


This will fail because of questionable design decision of having a 
mutable argument format:


LC_NUMERIC=fr_FR@UTF-8; printf 'Pi: %2.4f\n` "$(bc -l <<<'4*a(1)')"

Note how the format indicator still use a dot, but the argument format's 
decimal separator is that of the system's locale.


Imagine if C++ or Java had methods with different signature depending on 
system locale. You would scream fool. But for Bash, it was decided it 
was all fine.


--
Léa Gris




Re: EPOCHREALTIME

2021-08-19 Thread Ilkka Virta
On Thu, Aug 19, 2021 at 4:12 PM hancooper  wrote:

> On Thursday, August 19, 2021 12:58 PM, Léa Gris 
> wrote:
> > (LC_NUMERIC=C; echo "$EPOCHREALTIME")
>
> the unix time stamp is merely the number of
> seconds between a particular date and the epoch.  Technically, it should
> be pointed out
> that the time does not change no matter where you are located on the globe.
>
> Thusly, EPOCHREALTIME should not be made to depend on the locale.
>

The locale setting has more to do with which language you speak, rather
than where you are
(that would be the timezone). Even if the number is the same, it's
represented differently in
different languages, e.g. in Finnish, the comma would be the proper
separator, regardless
of if we speak Finnish in Finland, or in the US.

Regardless, one could argue that using the locale separator here is
counterproductive since
other utils, ones that can actually do calculations on the decimal number
(like bc), might not
support it. But for now, you can always use `${EPOCHREALTIME/,/.}` if you
need it with the
dot, no need to change locales.


EPOCHREALTIME

2021-08-19 Thread hancooper
‐‐‐ Original Message ‐‐‐
On Thursday, August 19, 2021 12:58 PM, Léa Gris  wrote:

> Le 19/08/2021 à 14:43, hancooper via Bug reports for the GNU Bourne
> Again SHell écrivait :
>
> > Have been using $EPOCHREALTIME but can see that the output is as follows.
> > 1629376497,853634
> > The utilisation of tho comma `,` is very inconvenient for those who want to 
> > do time
> > computations. A change towards a period `.` would be the proper way to 
> > display the
> > variable.
> > Furthermore, one gets nanosecond precision when using date. But such 
> > precision
> > is not possible with EPOCHREALTIME. Thusly, the improvement to nanosecond
> > precision is desirable so as to match the capability of data.
> > Felicitations
> > Han
>
> (LC_NUMERIC=C; echo "$EPOCHREALTIME")
>
> It will use a dot

time stamps are a way to track time as a running total of seconds, a count that 
starts
on January 1st, 1970 at UTC. Therefore, the unix time stamp is merely the 
number of
seconds between a particular date and the epoch.  Technically, it should be 
pointed out
that the time does not change no matter where you are located on the globe.

Thusly, EPOCHREALTIME should not be made to depend on the locale.  I have seen 
many
workarounds, that complicate rather than simplify something that should be 
straighforward
and germaine to direct numeric computation.





Re: EPOCHREALTIME

2021-08-19 Thread Léa Gris
Le 19/08/2021 à 14:43, hancooper via Bug reports for the GNU Bourne 
Again SHell écrivait :

Have been using $EPOCHREALTIME but can see that the output is as follows.

1629376497,853634

The utilisation of tho comma `,` is very inconvenient for those who want to do 
time
computations. A change towards a period `.` would be the proper way to display 
the
variable.

Furthermore, one gets nanosecond precision when using date. But such precision
is not possible with EPOCHREALTIME. Thusly, the improvement to nanosecond

precision is desirable so as to match the capability of data.

Felicitations
Han



(LC_NUMERIC=C; echo "$EPOCHREALTIME")

It will use a dot

--
Léa Gris




EPOCHREALTIME

2021-08-19 Thread hancooper via Bug reports for the GNU Bourne Again SHell
Have been using $EPOCHREALTIME but can see that the output is as follows.

1629376497,853634

The utilisation of tho comma `,` is very inconvenient for those who want to do 
time
computations. A change towards a period `.` would be the proper way to display 
the
variable.

Furthermore, one gets nanosecond precision when using date. But such precision
is not possible with EPOCHREALTIME. Thusly, the improvement to nanosecond

precision is desirable so as to match the capability of data.

Felicitations
Han

Re: @K transformation

2021-08-19 Thread Koichi Murase
2021年8月19日(木) 19:37 Léa Gris :
> Current implementation of @K is pretty-much useless for the dialog use-case:
>
> > #!/usr/bin/env bash
> >
> > declare -A assoc=(
> >   [P]=piano
> >   [TB]='foldable table'
> >   ['CH AIR']=chair
> > )
> >
> > options=("${assoc[@]@K}")

I this particular case, you can instead write

  declare -a "options=(${assoc[@]@K})"

though I agree that the behavior of zsh's ${(kv)assoc} (i.e.,
expanding to separate words) is more useful.  It's too late to change
the behavior of @K so maybe the new behavior can be assigned to @k if
it is worth implementing in Bash.

--
Koichi



Re: @K transformation

2021-08-19 Thread Léa Gris

Le 19/08/2021 à 12:09, Koichi Murase écrivait :


$ printf '<%s>\n' "${A[@]@A}"

<-A>


The problem of ${A[@]@A} is that it is not so useful when one wants to
define a clone associative array with a different name but with the
same contents as A. Instead, using ${A[@]@K}, one could do

$ declare -A "B=(${A[@]@K})"

to clone the associative array. It is even possible to save the
contents of an associative array in an indexed array as

$ declare -a "saved=(${A[@]@K})"

Hmm..., but for this case, one could actually simply store the
contents in a scalar:

$ saved="${A[*]@K}"



Current implementation of @K is pretty-much useless for the dialog use-case:


#!/usr/bin/env bash

declare -A assoc=(
  [P]=piano
  [TB]='foldable table'
  ['CH AIR']=chair
)

options=("${assoc[@]@K}")

#typeset -p options
#exit

choice="$(
  dialog \
--backtitle "Test" \
--title "Test" \
--menu "Test" \
0 0 4 \
"${options[@]}" \
2>&1 >/dev/tty
)"


Inline with "${array[@]}" expanding as multiple arguments!

"${assoc[@]@K}" shall have expanded into arguments and not expand quotes 
as string content.


This would have made the @K expansion usable for dialog.

Currently the associative array's key values pairs need be added to the 
options array in a for loop as:



options=()

for k in "${!assoc[@]}"; do
  options+=("$k" "${assoc[$k]}")
done



--
Léa Gris




Re: @K transformation

2021-08-19 Thread Koichi Murase
2021年8月19日(木) 18:16 Ilkka Virta :
> On Thu, Aug 19, 2021 at 5:49 AM Koichi Murase  wrote:
>> FYI, zsh provides this feature for associative arrays with the syntax
>> ${(kv)assoc} or ${(@kv)assoc}. Note that Bash-5.1 already has a
>> similar feature ${array[@]@K}, but the substitution result is quoted
>> so cannot be directly used for the present purpose.
>
>  $ declare -A A=([foo bar]="123 456" [adsf]="456 789")
> $ printf "<%s>\n" "${A[@]@K}"
> 
>
> Interesting. I wonder, what's the intended use-case for this?

I don't know the true background, but I guess it is designed as a
variant of ${A[@]@A} where the key-value pairs are compressed in a
single word:

$ printf '<%s>\n' "${A[@]@A}"

<-A>


The problem of ${A[@]@A} is that it is not so useful when one wants to
define a clone associative array with a different name but with the
same contents as A. Instead, using ${A[@]@K}, one could do

$ declare -A "B=(${A[@]@K})"

to clone the associative array. It is even possible to save the
contents of an associative array in an indexed array as

$ declare -a "saved=(${A[@]@K})"

Hmm..., but for this case, one could actually simply store the
contents in a scalar:

$ saved="${A[*]@K}"

-

I checked the change history. @K was introduced by commit 5f49ef47d

  
https://git.savannah.gnu.org/cgit/bash.git/commit/?id=5f49ef47d16efb9c8187cc5a193355599567fdd7

where a feature request by Sebastian Gniazdowski

  https://lists.gnu.org/archive/html/bug-bash/2019-07/msg00056.html

was mentioned. In this request, Sebastian has shown the following use case

> declare-A hash=( [key1]=val1 ['key2*[special-chars]']=val2 )
> printf -v serialized "%q " "${*hash[@]}"
> typeset -A deserialized_hash
> eval "deserialized_hash=($serialized)"

Maybe Chet guessed that the serialization is the only use case so that
the new transform can directly produce the serialized result.

Interestingly, Sebastian seems to have suggested ${*hash[@]} being
inspired by zsh's ${(kv)hash[@]}, so I think the original intention of
Sebastian had been that the new syntax would produce keys and values
as separate words.

--
Koichi



@K transformation

2021-08-19 Thread Ilkka Virta
On Thu, Aug 19, 2021 at 5:49 AM Koichi Murase 
wrote:

> FYI, zsh provides this feature for associative arrays with the syntax
> ${(kv)assoc} or ${(@kv)assoc}. Note that Bash-5.1 already has a
> similar feature ${array[@]@K}, but the substitution result is quoted
> so cannot be directly used for the present purpose.
>

 $ declare -A A=([foo bar]="123 456" [adsf]="456 789")
$ printf "<%s>\n" "${A[@]@K}"


Interesting. I wonder, what's the intended use-case for this?

The impression I have is that it's easier to turn a list of multiple words
into one
string (e.g. for display purposes), but much harder to keep things as
distinct
words (for pretty much anything else). So this seems to have a somewhat
limited
usefulness. I can see "${A[*]@K}" producing a single string like that, but
the same
with [@] seems odd compared to how [@] expansions otherwise work.