Re: wrong variable name in error message about unbound variable?
On Tue, 2023-10-17 at 00:26 -0400, Grisha Levit wrote: > The array subscript can an arbitrary arithmetic expression with side > effects, so it makes sense to perform the expansion even if the array > whose subscript is being expanded is unset: Okay... that's all pretty convoluted. I assume it boils down to the idea that a variable that's not an associative array may become automatically an indexed array, right? As Lawrence pointed out: $ set -u $ declare -A a $ echo ${a[k]} bash: a[k]: unbound variable Here it actually looks first at a (which turns out to be an associative array) and thus doesn't even bother to evaluate k, which makes sense of course, in order to avoid any side effects. Here, when a is still undeclared it still makes "sense" to evaluate the subscript, as a may even become a declared indexed array while doing so: $ set -u $ declare -p a bash: declare: a: not found $ echo ${a[a[4]=0]} bash: a[a[4]=0]: unbound variable $ declare -p a declare -a a=([4]="0") okay, makes sense to me. But: $ set -u $ declare -p a bash: declare: a: not found $ echo ${a[a[4]=4]} bash: a[a[4]=4]: unbound variable $ declare -p a declare -a a=([4]="4") Why does it say unbound here? a[4]=4 should evaluate to 4 and also set the index 4, right? Cheers, Chris.
Re: wrong variable name in error message about unbound variable?
Hey. On Mon, 2023-10-16 at 22:05 -0400, Lawrence Velázquez wrote: > Under no circumstances should your examples complain about "array" > because they do not attempt to expand it. As I demonstrated, your > examples do not even complain about unset scalar variables. Okay I realise now, why it worked once it was declared an associative array. But why does it even try to evaluate the subscript "key" as arithmetic expression? Yes it's defined for indexed arrays, but shouldn't it already know that there is no indexed array of the name "array" and any evaluation of the subscript is thus pointless? And a follow up question on this (guess its pointless to post this now on help-bash): When one just wants to check whether some var[key] is set with var being an associative array and assuming that set -u might be in effect. It's obviously not enough to do: [[ -v var[key] ]] - in an indexed array it would do arithmetic evaluation of the key and might give a false positive as in: $ declare -a a $ a[3]=foo $ key='1+2' $ [[ -v a[key] ]]; echo $? 0 - or as above, it might yield nothing but give the unbound error One cannot use e.g ${var@a} or ${var@A} either as these would already give unbound errors if the variable is not set (declaring it wouldn't suffice either). So AFAICS, the only way is to match the output of "declare -p var" for "declare -A *" and only then to the [[ -v ... ]]? Or would it make sense to exempt @a and @A form set -u? Thanks, Chris.
wrong variable name in error message about unbound variable?
Hey. On 5.2.15 I've noticed the following: $ set -u $ [ -n "${array[key]+is_set}" ] && echo is set || echo not set bash: key: unbound variable $ [[ -v array[key] ]] && echo is set || echo not set bash: key: unbound variable $ declare -A array $ [ -n "${array[key]+is_set}" ] && echo is set || echo not set not set $ [[ -v array[key] ]] && echo is set || echo not set not set Once array is declared (not even anything of it set yet) it gives already no unbound error. So shouldn't the error message refer to "array" as the unbound variable? Or perhaps both "array[key]"? Because the problem isn't that no key named "key" exists. And beyond that: POSIX says: > -u >When the shell tries to expand an unset parameter other than the >'@' and '*' special parameters, it shall write a message to >standard error and the expansion shall fail with the consequences >specified in Consequences of Shell Errors. But just declaring the var, doesn't make it set... so shouldn't it still give an error message (which it does when using a non-array variable that is declared but not set)? Cheers, Chris.
Re: definite way to determine the running shell
On Fri, 2015-03-27 at 01:44 -0600, Eduardo A. Bustamante López wrote: Why would the user set BASH_VERSION in the environment? That sounds like asking for trouble! Murphy's law! :D - try to unset BASHOPTS (did it work? then it's not bash) - Now, store the value of BASHOPTS in a temp var - Set a shopt option that's not set already in BASHOPTS (or unset one from BASHOPTS) - Check if the value of BASHOPTS changed. that sounds like a nice idea. I just thought about another solution myself PATH= shopt then only a shell having shopt (hopefully that is just bash) should give $?=0 . Thanks, Chris. smime.p7s Description: S/MIME cryptographic signature
Re: definite way to determine the running shell
On Fri, 2015-03-27 at 15:11 -0400, Greg Wooledge wrote: OK, this is for some personal configuration management. Well it's rather for some 1000 institute workstations,... Not as part of a product you're deploying, etc. As such, presumably you are not trying to trick yourself into breaking your own logins or shell startups. ... and you never really know what strange thins users accidentally do ;) So, just check for $BASH_VERSION and you should be all right. Sure,... I just wanted to as, whether there's maybe a much more obvious fool-proof solution :) Though, if it were me, I'd just simplify everything. Don't use so many different shells, don't use such complicated aliases that you have to have multiple versions of them I personally just use bash (except for sh where it's dash)... but see above :) Cheers, Chris. smime.p7s Description: S/MIME cryptographic signature
Re: definite way to determine the running shell
On Fri, 2015-03-27 at 08:56 +0100, Andreas Schwab wrote: Why do you need to know that? Well there are so many use cases... my particular one is, that many shells share config files (e.g. .profile) and for other cases (e.g. aliases definitions) it would be handy if one could set up a sourcable script, which does the necessary stuff, automatically in the way for the current shell. Cheers, Chris. smime.p7s Description: S/MIME cryptographic signature
Re: definite way to determine the running shell
On Fri, 2015-03-27 at 14:56 -0400, Greg Wooledge wrote: ... why are you running test suites in your .bashrc?? As said, I'd find it nice to have one aliases file for all shells, and that would in turn then be sourced from either .profile or rather .bashrc... so while tests wouldn't run in .bashrc itself, they'd always be executed along. smime.p7s Description: S/MIME cryptographic signature
definite way to determine the running shell
Hey. There are a lot of articles on the web about detecting the actually running shell. Unfortunately, just relying on $SHELL doesn't really work since when I invoke e.g. csh from bash, it would be still $SHELL=bash and I guess I won't be able to convince all shell upstreams to overwrite $SHELL (which IMHO would be much better, and more like $TERM). Now I see basically two other ways to detect a shell: a) using ps or something similar... which is not really portable either and can be rather easily/accidentally fooled b) Using some env vars typically to the shell, e.g. BASH_VERSION for bash. AFAIU per default these are not declared'ed -x , so when I rund fooShell from bash it wouldn't be inherited. But the user could still manually mark it exportable. c) I've also thought about somehow using e.g. shopt, when it runs I could be sure, it was bash. But for that in turn I'd need to make sure whether it's a built-in command, which works in bash with the builtin built in command ;) ... but not portably as in POSIX shell command language (at least not that I'd know). Is there some better way to do this (at least to detect bash)? E.g. some VAR that bash sets and that it would neither take from its own environment when being started nor that it would pass on to processes? Thanks, Chris. smime.p7s Description: S/MIME cryptographic signature
Re: feature-request: don't count history time comment lines when in HISTFILESIZE
On Thu, 2015-03-26 at 16:26 -0400, Chet Ramey wrote: And b) it seems kinda ugly that one needs to explicitly set a default value that would be set later anyway. Maybe. Okay, keep me tuned if you should plan to actually do that, cause then I can revise manually setting it :) It is what it is, and it's an effective workaround that you can use today. Sure, thanks for that,... Wasn't it possible to simply set the default for histchars earlier in the startup? histchars defaulting is part of the interactive shell setup; environment variables are scanned before any other setup so they are available when the startup files are read. The interactive shell startup comes after the startup files are read so the startup files can set any appropriate variables. One other possibility would be, if HISTTIMEFORMAT is set and histchars is not, while you read in the .bash_history, assume only there the default of # and ignore these lines. That way would probably not change the behaviour a lot. Cheers, Chris.
Re: feature-request: don't count history time comment lines when in HISTFILESIZE
On Thu, 2015-03-26 at 15:21 -0400, Chet Ramey wrote: What do you mean ignore its effect? You have newlines embedded in history entries; what do you plan to do about them? Well that was just the uneducated idea based on blind assumptions by *not* having read the code O:-) AFAIU, both already works: - if cmdhist=on lithist=off = we get the if true; then echo foo ; fi layout for both history and history file + in both cases each command stays one command. - if cmdhist=on lithist=on = we get the layout with embedded newlines in the history (with each command staying one command), but in the history file it breaks and the multiline command is split up in several commands Right? So why not make a thrid mode like: - if cmdhist=on lithist=not-in-file which keeps: if true; then\n echo foo\n fi in the history but writes the serialised if true; then echo foo ; fi to the history file. Of course on re-loading the history it would again be the form without \n, but better having the serialised form than mutliple commands. And it would then at least work for the current command history Cheers, Chris.
Re: feature-request: don't count history time comment lines when in HISTFILESIZE
On Thu, 2015-03-26 at 16:54 -0400, Chet Ramey wrote: The solution cannot be bash-specific; the history library is used by many other applications. One, design-wise ugly, idea: Couldn't you abuse the history comment char another time for that? Like consider anything between a ^#[[:digit:]] to be part of one command: With HISTTIMEFORMAT set that could look like: #1427416260 echo foo #1427416363 if true; then echo bar fi #1427416625 ./and_so_on If HISTTIMEFORMAT is not set, you could simply write 0 #0 echo foo #0 if true; then echo bar fi #0 ./and_so_on AFAICS, this wouldn't break compatibility - anything that matches ^#[[:digit:]] is already now not stored in the history files, AFAICS - of course one would probably need to clear the history when one enables the shopt for using the above schema (or otherwise one could see extremely big multiline commands) Or one may just start with that way of parsing the file, the first time a ^#[[:digit:]] is encountered, and anything before is considered to be single commands per line. Cheers, Chris.
feature-request: don't count history time comment lines when in HISTFILESIZE
Hey. When HISTTIMEFORMAT is used the history time comment lines are written to HISTFILE. Therefore, HISTFILESIZE is effectively only half as large. Would it be possible to simply not count the history time comment lines when enforcing HISTFILESIZE? Cheers, Chris.
Re: feature-request: don't count history time comment lines when in HISTFILESIZE
On Wed, 2015-03-25 at 14:48 -0400, Chet Ramey wrote: The history file truncation code already skips lines that look like history timestamps. Look at history.c:history_truncate_file(). Ah? Hmm was that only recently introduced? I'm having bash4.3 with patches up to including 33. And this time I looked whether Debian added any of it's goodness ;-) When I set e.g. in .bashrc: HISTSIZE=50 HISTFILESIZE=50 HISTTIMEFORMAT=$'%c\t' Then: $ rm .bash_history $ history -c Then start a new shell and then enter commands $ echo 1 $ echo 2 ... $ echo 50 When I do now a: $ history I see all the 50 (+/- 1) But when I leave the shell and go into a new one: $ histroy gives me only about the last 25 (i.e. echo 27 to echo 50 + history), and these are also the only entries in .bash_history, i.e.: #1427309882 echo 27 #1427309882 echo 28 [snip snap] #1427309882 echo 50 #1427309884 history Cheers, Chris.
Re: feature-request: don't count history time comment lines when in HISTFILESIZE
On Wed, 2015-03-25 at 16:21 -0400, Chet Ramey wrote: https://lists.gnu.org/archive/html/bug-bash/2011-02/msg00042.html Maybe I've missed something but that thread basically just discussed the same issue without giving a solution, right? I understand you concerns about any format changes, that's why my idea was to allow lithist set but ignore it's effect when the history file is written... wouldn't that work out? Cheers, Chris.
Re: feature-request: don't count history time comment lines when in HISTFILESIZE
On Wed, 2015-03-25 at 16:19 -0400, Chet Ramey wrote: When you start bash, and source your .bashrc, the history comment character is not set. You haven't set it in .bashrc, I assume Yes, I haven't. Since that's not set, the lines beginning with `#[digit]' are not recognized as timestamps and treated as ordinary history entries. You can fix this by assigning to histchars before setting HISTFILESIZE: histchars='!^#' Okay that works in principle. But a) this means truncation of the history file happens immediately each the HISTFILESIZE is set and not just when the shell quits, right? And b) it seems kinda ugly that one needs to explicitly set a default value that would be set later anyway. Wasn't it possible to simply set the default for histchars earlier in the startup? If someone wants to set histchars he'd have to do it anyway, and for those who want to stick with the defaults, this would solve the above issue. Apart from that, it's not really directly obvious that histchars also affects the history itself and not just history expansion. E.g. it's normally not even set in my shell environment (not even the default value). Thanks, Chris.
bug in documentation?
Hey. The bash manpage says: When a login shell exits, bash reads and executes commands from the file ~/.bash_logout, if it exists. However, it seems that this happens only for interactive login shells,... at least I couldn't get it executed for non-interactive login shells with the --login option. Could you please clarify that? Thanks, Chris. smime.p7s Description: S/MIME cryptographic signature
Re: bug in documentation?
Hey. On Sun, 2015-03-22 at 22:08 -0400, Chet Ramey wrote: It does when you call the exit builtin. EOF to an interactive shell executes the exit builtin, but you have to explicitly call it when in a non-interactive shell. Ah... tricky :D Okay could you then please add this? Guess many others would also never found out without asking. Cheers, Chris. smime.p7s Description: S/MIME cryptographic signature