Re: Add option to just print history, with no added timestamps or line numbers
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." > >
Re: ${var@A}; hypothetical, related parameter transformations
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: "${assoc[@]@k}" doesn't get expanded to separate words within compound assignment syntax
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: "${assoc[@]@k}" doesn't get expanded to separate words within compound assignment syntax
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
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
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
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
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
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
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
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
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: Add option to just print history, with no added timestamps or line numbers
> "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: Add option to just print history, with no added timestamps or line numbers
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
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: History Expansion in Arithmetic Expansion
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
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: Add option to just print history, with no added timestamps or line numbers
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.