Re: Add option to just print history, with no added timestamps or line numbers

2024-03-24 Thread Dan Jacobson
Hmm, so no matter POSIX mode or not, both will be dragging around that
little piece of toilet paper stuck to their shoes (\t)... unless some
new option is invented.



Re: Add option to just print history, with no added timestamps or line numbers

2024-03-24 Thread Lawrence Velázquez
On Sun, Mar 24, 2024, at 11:01 PM, Dan Jacobson wrote:
> P.S., "\t%s" seems to have an extra space squeezed between them with 
> bash: "\t %s",
> unless perhaps the spec says that %s always starts with a space.

The standard doesn't say that, so in native mode bash's `fc' is
indeed slightly nonconformant, but in POSIX mode it does omit the
extra space.

$ set +o posix
$ fc -ln -1 | od -t c -t x1
000   \t   s   e   t   +   o   p   o   s   i   x  \n
   09  20  73  65  74  20  2b  6f  20  70  6f  73  69  78  0a
017
$ set -o posix
$ fc -ln -1 | od -t c -t x1
000   \t   s   e   t   -   o   p   o   s   i   x  \n
   09  73  65  74  20  2d  6f  20  70  6f  73  69  78  0a
016

-- 
vq



Re: History Expansion in Arithmetic Expansion

2024-03-24 Thread Zachary Santer
On Sat, Mar 23, 2024 at 11:34 AM A4-Tacks  wrote:
>
>  ```bash
>  $ ((!RANDOM))
>  bash: !RANDOM: event not found
>  ```

I just reported this last August [1]. If you, like me, never use
history expansion, the best solution might be to disable it in your
.bashrc file:
set +o histexpand
or
set +H
if you hate readability.

$ printf '%s\n' "$(( !RANDOM ))"
0

[1]: https://lists.gnu.org/archive/html/bug-bash/2023-08/msg00016.html



Re: Add option to just print history, with no added timestamps or line numbers

2024-03-24 Thread Dan Jacobson
How unfortunate.
P.S., "\t%s" seems to have an extra space squeezed between them with bash: "\t 
%s",
unless perhaps the spec says that %s always starts with a space.



Re: Add option to just print history, with no added timestamps or line numbers

2024-03-24 Thread Lawrence Velázquez
On Sun, Mar 24, 2024, at 8:54 PM, Dan Jacobson wrote:
> Yes, it omits the line numbers. But leaves the "^I " separators!
>
> $ fc -l 999 1000|cat -vt
> 999^I echo invite Nerbleson for dinner
> 1000^I echo and Snordsworth too
> $ fc -ln 999 1000|cat -vt
> ^I echo invite Nerbleson for dinner
> ^I echo and Snordsworth too

This behavior is standardized by POSIX.

When the -l option is used to list commands, the format of
each command in the list shall be as follows:

"%d\t%s\n", , 

If both the -l and -n options are specified, the format of
each command shall be:

"\t%s\n", 

https://pubs.opengroup.org/onlinepubs/9699919799/utilities/fc.html

-- 
vq



Re: Add option to just print history, with no added timestamps or line numbers

2024-03-24 Thread Dan Jacobson
> "MDK" == Martin D Kealey  writes:
MDK> How about « fc -ln » ?

I like it!

P.S.,

$ help fc
  -nomit line numbers when listing

Yes, it omits the line numbers. But leaves the "^I " separators!

$ fc -l 999 1000|cat -vt
999^I echo invite Nerbleson for dinner
1000^I echo and Snordsworth too
$ fc -ln 999 1000|cat -vt
^I echo invite Nerbleson for dinner
^I echo and Snordsworth too

(Well I guess that's better than the other way around at least.
(Inserting the numbers but forgetting the separators.))

MDK> It might be helpful to have explicit cross-references between the
MDK> help displays for «history» and «fc».

Yup, else I would have never learned about this feature unless the nice
man from .nz stepped forth. Imagine that, me, an innocent reader of the
"help history" command, is supposed to magically know about the "fc"
command, without a shred of "SEE ALSO" there on the "help history" page.
Yes, we are all supposed to read the Bash Man page, but a tiny 'see also
"fc"' would go miles in making "help" more helpful.



Re: "${assoc[@]@k}" doesn't get expanded to separate words within compound assignment syntax

2024-03-24 Thread Dennis Williamson
On Sun, Mar 24, 2024 at 4:04 PM Greg Wooledge  wrote:

> The @K (capital) transformation gives you quoted strings which need to
> be eval'ed.  Very Bourne-shell-ish.
>
> The @k (lowercase) transformation gives you a list of alternating raw
> key/value strings, like what you'd expect from a Tcl command.
>

I apologize. I didn't test the transforms properly.

>> Thus the @K allows preserving indices in a sparse
>> indexed array.

> Both of them do that:

Yes. I didn't mean to imply that one didn't. The main point I intended to
make was that your statement

>>> The main difference would be that with an indexed array, every argument
after the array name becomes an array element, instead of half of them
being keys and the other half being values.

missed that.

-- 
Visit serverfault.com to get your system administration questions answered.


Re: "${assoc[@]@k}" doesn't get expanded to separate words within compound assignment syntax

2024-03-24 Thread Greg Wooledge
On Sun, Mar 24, 2024 at 03:54:10PM -0500, Dennis Williamson wrote:
> The @K transform outputs key value pairs for indexed arrays as well as
> associative arrays (you used the @k transform which does word splitting and
> loses the k-v sequence).

The @K (capital) transformation gives you quoted strings which need to
be eval'ed.  Very Bourne-shell-ish.

The @k (lowercase) transformation gives you a list of alternating raw
key/value strings, like what you'd expect from a Tcl command.

hobbit:~$ unset -v hash kvlist
hobbit:~$ declare -A hash=([key 1]='value 1' [key 2]='value 2')
hobbit:~$ kvlist=( "${hash[@]@k}" )
hobbit:~$ declare -p kvlist
declare -a kvlist=([0]="key 2" [1]="value 2" [2]="key 1" [3]="value 1")
hobbit:~$ kvlist2=( "${hash[@]@K}" )
hobbit:~$ declare -p kvlist2
declare -a kvlist2=([0]="\"key 2\" \"value 2\" \"key 1\" \"value 1\" ")
hobbit:~$ eval kvlist3=\("${hash[@]@K}"\)
hobbit:~$ declare -p kvlist3
declare -a kvlist3=([0]="key 2" [1]="value 2" [2]="key 1" [3]="value 1")

kvlist2 is an undesired result.  Don't do that.  kvlist and kvlist3 are
both usable.

> Thus the @K allows preserving indices in a sparse
> indexed array.

Both of them do that:

hobbit:~$ sparse=(a b [42]=z)
hobbit:~$ echo "${sparse[@]@K}"
0 "a" 1 "b" 42 "z"
hobbit:~$ echo "${sparse[@]@k}"
0 a 1 b 42 z



Re: "${assoc[@]@k}" doesn't get expanded to separate words within compound assignment syntax

2024-03-24 Thread Dennis Williamson
On Sun, Mar 24, 2024 at 1:56 PM Greg Wooledge  wrote:

> It would be pretty reasonable to have a builtin that could take an array
> name plus any number of additional argument pairs, and load those pairs
> as keys/values into said array.  Then you could do something like this:
>
> declare -A hash=(...)
> kvlist=( "${hash[@]@k}" )
>
> declare -A newhash
> addtoarray newhash "${kvlist[@]}"
>
> Some readers may observe that this looks a bit like Tcl's "array set"
> command.  That's not a coincidence.  Whenever I see "a list of alternating
> keys and values", that's where my mind goes.
>
> I'm debating mentally whether this hypothetical new builtin would only
> work with associative arrays, or also double as an "lappend" (append new
> elements to the end of a list/array) if given an indexed array name.
> I'm leaning toward having it be both.  It wouldn't be any *more* confusing
> than the current situation already is.  The main difference would be that
> with an indexed array, every argument after the array name becomes an
> array element, instead of half of them being keys and the other half
> being values.
>
> Then again, I'm not likely to attempt to implement it, so anyone who
> actually writes the code gets to make all the decisions.
>
>
The @K transform outputs key value pairs for indexed arrays as well as
associative arrays (you used the @k transform which does word splitting and
loses the k-v sequence). Thus the @K allows preserving indices in a sparse
indexed array. So your hypothetical builtin would only depend on the type
of the receiving array. So it wouldn't be every argument as an element - it
would still be keys (indices) and values alternating.

declare -A hash=(...)
kvlist=( "${hash[@]@K}" )

declare -A newhash
addtoarray newhash "${kvlist[@]}"

declare -a indexed=(...)# or initialized / built up in another way
- with sequential or sparse indices
kvlist=( "${indexed[@]@K}" )

declare -a newindexed # or omitted
addtoarray newindexed "${kvlist[@]}"

addtoarray should have options for dealing with index collisions (last wins
(default), first wins, error, warning) and a clear before adding would be
handy but trivial to do in a script. Another handy but not needed feature
would be an option to declare the receiving array and add to it in one go.

I'm also unlikely to implement it.

-- 
Visit serverfault.com to get your system administration questions answered.


Re: "${assoc[@]@k}" doesn't get expanded to separate words within compound assignment syntax

2024-03-24 Thread Lawrence Velázquez
On Sun, Mar 24, 2024, at 2:56 PM, Greg Wooledge wrote:
> On Sun, Mar 24, 2024 at 01:04:38PM -0400, Zachary Santer wrote:
>> On Fri, Mar 22, 2024 at 11:23 AM Chet Ramey  wrote:
>> >
>> > This is what you can do with @K.
>> >
>> > https://lists.gnu.org/archive/html/bug-bash/2021-08/msg00119.html
>> >
>> > Word splitting doesn't happen on the rhs of an assignment statement, so you
>> > use eval. The @K quoting is eval-safe.
>> 
>> Yeah, but what can you do with @k?
>
> You can write the keys and values to a stream/file.

I guess you can also more easily iterate over them or move them to
an indexed array (as has already been demonstrated).  I'm not really
sure this merited its own parameter transformation, but then again
that's how I feel about most of the transformations.


>> The difference in expansion behavior between indexed and associative
>> array compound assignment statements doesn't make sense.

The behavior of the latter is for backward compatibility, I think.
Initially expansions could only be used in associative array compound
assignments like this, so word splitting was undesirable:

declare -A x=([$y]=$z)

I suppose the contents of x=(...) could be examined lexically to
determine whether splitting should be allowed, but that would make
the situation even messier.


> It would be pretty reasonable to have a builtin that could take an array
> name plus any number of additional argument pairs, and load those pairs
> as keys/values into said array.  Then you could do something like this:
>
> declare -A hash=(...)
> kvlist=( "${hash[@]@k}" )
>
> declare -A newhash
> addtoarray newhash "${kvlist[@]}"
>
> Some readers may observe that this looks a bit like Tcl's "array set"
> command.  That's not a coincidence.  Whenever I see "a list of alternating
> keys and values", that's where my mind goes.
>
> I'm debating mentally whether this hypothetical new builtin would only
> work with associative arrays, or also double as an "lappend" (append new
> elements to the end of a list/array) if given an indexed array name.

Incidentally, yash has an "array" builtin that works like this on
indexed arrays.  (Yash doesn't have associative arrays.)

https://magicant.github.io/yash/doc/_array.html


-- 
vq



Re: "${assoc[@]@k}" doesn't get expanded to separate words within compound assignment syntax

2024-03-24 Thread Oğuz
On Sunday, March 24, 2024, Oğuz  wrote:
>
> $ printf '%s\0' "${a[@]@k}" | xargs -0 jq --args -n '$ARGS.positional
> | _nwise(2) | {(.[0]): .[1]}' | jq -s add
>

On reflection, splitting by NULs in JQ is better; there is no guarantee
that xargs will always provide an even number of arguments.


-- 
Oğuz


Re: "${assoc[@]@k}" doesn't get expanded to separate words within compound assignment syntax

2024-03-24 Thread Oğuz
On Sunday, March 24, 2024, Greg Wooledge  wrote:

> Conceptually that looks great, but how do you avoid "Argument list
> too long" with larger inputs?


$ declare -A a=([x]=1 [y]=2)
$ printf '%s\0' "${a[@]@k}" | xargs -0 jq --args -n '$ARGS.positional |
_nwise(2) | {(.[0]): .[1]}' | jq -s add
{
  "y": "2",
  "x": "1"
}


-- 
Oğuz


Re: "${assoc[@]@k}" doesn't get expanded to separate words within compound assignment syntax

2024-03-24 Thread Greg Wooledge
On Sun, Mar 24, 2024 at 07:46:46PM +0200, Oğuz wrote:
> On Sunday, March 24, 2024, Zachary Santer  wrote:
> >
> > Yeah, but what can you do with @k?
> 
> 
> It helps when reconstructing an associative array as a JSON object in JQ
> 
> $ declare -A a=([x]=1 [y]=2)
> $ jq --args -n '[$ARGS.positional | _nwise(2) | {(.[0]): .[1]}] | add'
> "${a[@]@k}"
> {
>   "y": "2",
>   "x": "1"
> }

Conceptually that looks great, but how do you avoid "Argument list
too long" with larger inputs?

I've got this example on hand, but it doesn't include a hash:

hobbit:~$ a=("an array" "of strings"); b="a string"; printf '%s\0' "${a[@]}" | 
jq -R --arg b "$b" '{list: split("\u"), string: $b}'
{
  "list": [
"an array",
"of strings"
  ],
  "string": "a string"
}



Re: "${assoc[@]@k}" doesn't get expanded to separate words within compound assignment syntax

2024-03-24 Thread Greg Wooledge
On Sun, Mar 24, 2024 at 01:04:38PM -0400, Zachary Santer wrote:
> On Fri, Mar 22, 2024 at 11:23 AM Chet Ramey  wrote:
> >
> > This is what you can do with @K.
> >
> > https://lists.gnu.org/archive/html/bug-bash/2021-08/msg00119.html
> >
> > Word splitting doesn't happen on the rhs of an assignment statement, so you
> > use eval. The @K quoting is eval-safe.
> 
> Yeah, but what can you do with @k?

You can write the keys and values to a stream/file.  That's pretty
much it -- but that's actually not too shabby.  Imagine sharing a bash
associative array with some other programming language and wanting to
import it into that other language's dictionary/hash data structure.
This is what you'd want.

> The difference in expansion behavior between indexed and associative
> array compound assignment statements doesn't make sense. As nice as it
> is to have expansions that expand to eval-safe expressions, needing
> eval less would be nicer.

It would be pretty reasonable to have a builtin that could take an array
name plus any number of additional argument pairs, and load those pairs
as keys/values into said array.  Then you could do something like this:

declare -A hash=(...)
kvlist=( "${hash[@]@k}" )

declare -A newhash
addtoarray newhash "${kvlist[@]}"

Some readers may observe that this looks a bit like Tcl's "array set"
command.  That's not a coincidence.  Whenever I see "a list of alternating
keys and values", that's where my mind goes.

I'm debating mentally whether this hypothetical new builtin would only
work with associative arrays, or also double as an "lappend" (append new
elements to the end of a list/array) if given an indexed array name.
I'm leaning toward having it be both.  It wouldn't be any *more* confusing
than the current situation already is.  The main difference would be that
with an indexed array, every argument after the array name becomes an
array element, instead of half of them being keys and the other half
being values.

Then again, I'm not likely to attempt to implement it, so anyone who
actually writes the code gets to make all the decisions.



Re: "${assoc[@]@k}" doesn't get expanded to separate words within compound assignment syntax

2024-03-24 Thread Oğuz
On Sunday, March 24, 2024, Zachary Santer  wrote:
>
> Yeah, but what can you do with @k?


It helps when reconstructing an associative array as a JSON object in JQ

$ declare -A a=([x]=1 [y]=2)
$ jq --args -n '[$ARGS.positional | _nwise(2) | {(.[0]): .[1]}] | add'
"${a[@]@k}"
{
  "y": "2",
  "x": "1"
}


-- 
Oğuz


Re: "${assoc[@]@k}" doesn't get expanded to separate words within compound assignment syntax

2024-03-24 Thread Zachary Santer
On Fri, Mar 22, 2024 at 11:23 AM Chet Ramey  wrote:
>
> This is what you can do with @K.
>
> https://lists.gnu.org/archive/html/bug-bash/2021-08/msg00119.html
>
> Word splitting doesn't happen on the rhs of an assignment statement, so you
> use eval. The @K quoting is eval-safe.

Yeah, but what can you do with @k?

$ unset assoc array assoc_copy
$ declare -A assoc=( [zero]=0 [one]=1 [two]=2 )
$ declare -a array=( "${assoc[@]@k}" )
$ eval "declare -A assoc_copy=( ${assoc[*]@K} )"
$ declare -p assoc array assoc_copy
declare -A assoc=([two]="2" [one]="1" [zero]="0" )
declare -a array=([0]="two" [1]="2" [2]="one" [3]="1" [4]="zero" [5]="0")
declare -A assoc_copy=([two]="2" [one]="1" [zero]="0" )

The difference in expansion behavior between indexed and associative
array compound assignment statements doesn't make sense. As nice as it
is to have expansions that expand to eval-safe expressions, needing
eval less would be nicer.



Re: ${var@A}; hypothetical, related parameter transformations

2024-03-24 Thread Zachary Santer
On Thu, Mar 21, 2024 at 4:08 PM Chet Ramey  wrote:
>
> On 3/20/24 3:05 PM, Zachary Santer wrote:
>
> > it's more work
> > than if there were three separate parameter transformations. one each
> > to always generate a declare command; an assignment statement; and the
> > right hand side of a compound assignment statement or standard
> > assignment statement, depending on whether it's dealing with an
> > array/assoc or scalar.
>
> I am not convinced that tripling the number of relevant variable
> transformations makes the problem any simpler.

It's simpler in the sense that the bash programmer can choose the
behavior they want and are guaranteed to get it.

On Thu, Mar 21, 2024 at 4:12 PM Chet Ramey  wrote:
>
> If you want to be guaranteed a declare command for a particular name,
> use `declare -p'. Parse the result of a (nofork) command substitution
> if you must.

That's fair. I kind of figured ${var@A} was intended to replace 'declare -p'.



Re: Add option to just print history, with no added timestamps or line numbers

2024-03-24 Thread Martin D Kealey
Hi Dan

How about « fc -ln » ?

It might be helpful to have explicit cross-references between the help
displays for «history» and «fc».

-Martin

On Sun, 24 Mar 2024 at 15:40, Dan Jacobson  wrote:

> $ help history
> should mention how in the world one is supposed to just print the plain
> history,
> without any line numbers or time stamps.
>
> You might say, "Just strip it off with perl or sed." Well, fine. Then
> mention that in help history.
>
> Currently one needs massive superfund environmental clean-up effort
> workarounds, e.g.,
> $ HISTTIMEFORMAT=' ' history | perl -pwle 's/^\s+\S+\s+//'
>
> Better yet, add a
> history -j: Just print history, with no added timestamps or line numbers,
> etc.
>
> Or OK, there's HISTTIMEFORMAT. How about also a HISTFORMAT (default " %5n
> %t %h\n" or whatever,) so one could use "%h\n" for "just give me the
> history item."
>
>