How to initialize a read-only, global, associative array in Bash?
Hi folks, I execute the following code in Bash version "GNU bash, Version 4.2.39(1)-release (x86_64-redhat-linux-gnu)": function foobar { declare -rgA FOOBAR=([foo]=bar) } foobar declare -p FOOBAR # Output: declare -Ar FOOBAR='()' Why doesn't Bash initialize FOOBAR with ([foo]=bar) according to declare -p? The same declaration works outside of a function, e.g. declare -rgA FOOBAR=([foo]=bar) declare -p FOOBAR # Output: declare -Ar FOOBAR='([foo]="bar" )' Similarly the following code but without FOOBAR being read-only works: function foobar { declare -gA FOOBAR FOOBAR=([foo]=bar) } foobar declare -p FOOBAR # Output: declare -A FOOBAR='([foo]="bar" )' Is this a bug or feature? Cheers, Tim BTW: I couldn't find a "bashbug" RPM package in the Fedora 17 repositories; that's why I wrote this formless mail. Sorry for that. -- `°< C92A E44E CC19 58E2 FA35 4048 2217 3C6E 0338 83FC
Why is not every variable initialized to its data type specific default value upon declaration in Bash?
Hi folks, when I execute the following code in Bash version "GNU bash, version 4.1.10(4)-release (i686-pc-cygwin)", I get: declare a declare -p a # Output: -bash: declare: a: not found declare -i b declare -p b # Output: -bash: declare: b: not found declare -a c declare -p c # Output: declare -a c='()' declare -A d declare -p d # Output: declare -A d='()' Arguably I think that the above variables should either be initialized in all cases or in none of them. That would seem more consistent rather than initializing only arrays upon declaration. Cheers, Tim -- `°< C92A E44E CC19 58E2 FA35 4048 2217 3C6E 0338 83FC
How to presence-detect an array variable or subscript thereof with `test -v`?
Hi folks, I came accross the `-v` option of the `test` command and wondered how I would possibly test not only string- and integer- but also array variables as a whole and in parts. I thought it should be possible to say: declare -Ai foobar=([bar]=0) test -v foobar[foo] && echo true || echo false # Output: true test -v foobar[bar] && echo true || echo false # Output: true Even quoting doesn't help here except for the opposite results: test -v "foobar[foo]" && echo true || echo false # Output: false test -v "foobar[bar]" && echo true || echo false # Output: false Obviously the results should be "false" and "true", respectively. Apart from arrays everything else works as follows: test -v a && echo true || echo false # Output: false declare a="" test -v a && echo true || echo false # Output: true test -v b && echo true || echo false # Output: false declare -i b=0 test -v b && echo true || echo false # Output: true test -v c && echo true || echo false # Output: false declare -a c=() test -v c && echo true || echo false # Output: true Cheers, Tim -- -- `°< C92A E44E CC19 58E2 FA35 4048 2217 3C6E 0338 83FC
Strange re-initialization of array. Bug or feature?
Hi folks, I execute the following code with Bash version "GNU bash, Version 4.2.39(1)-release (x86_64-redhat-linux-gnu)" on Fedora 17: # Returns 0 else 1 if the sourcing (source) script isn't keyed by its base name in the global "ONCE" array yet. # # A script should include this script near the top with "source me_once || return 0" in order to get sourced itself only # once. # # @return 0 on success, n != 0 on failure. # function me_once { unset -f me_once if [[ ! -v ONCE ]]; then echo AAA declare -gAi ONCE=() fi echo BBB declare -p ONCE declare -r a="${BASH_SOURCE[2]##*/}" if (( ${ONCE[$a]:+1} )); then return 1 else ONCE+=(["$a"]=1) echo CCC declare -p ONCE fi } me_once If sourced at least twice from another script I get the following output printed: AAA BBB declare -A ONCE='()' CCC declare -A ONCE='([std.bash]="1" )' BBB declare -Ai ONCE='()' CCC declare -Ai ONCE='([std.bash]="1" )' If I remove the initialization "=()" from "declare -gAi ONCE" I get the following output printed: AAA BBB declare -Ai ONCE='()' CCC declare -Ai ONCE='([std.bash]="1" )' BBB declare -Ai ONCE='([std.bash]="1" )' The "declare -gAi ONCE=()" seems to get executed every time although surrounded by "[[ ! -v ONCE ]]" whereas "echo AAA" within the same if-block only the first time. Is this a bug or feature? Cheers, Tim -- -- `°< C92A E44E CC19 58E2 FA35 4048 2217 3C6E 0338 83FC
Why can't I say "&>&3"? Bug or feature?
Hi folks, why is it that I can't say: exec 3>/dev/null echo foobar &>&3 # Error: "-bash: syntax error near unexpected token `&'" but the following works: echo foobar &>/dev/null echo foobar >&3 2>&3 I think the succinct notation "&>&N" where N is some numbered file descriptor should work also. Is this behavior a bug or feature? Cheers, Tim -- `°< C92A E44E CC19 58E2 FA35 4048 2217 3C6E 0338 83FC
Bash's declare -p HISTIGNORE brings bash to a halt! Why?
Hi, executing the following code in GNU bash, Version 4.2.45(1)-release (x86_64-redhat-linux-gnu), Fedora 19 ... shopt -s extglob export HISTIGNORE="!(+(!([[\:space\:]]))+([[\:space\:]])+(!([[\:space\:]])))" declare -p HISTIGNORE ... brings bash to a full stop. It does not print a command prompt hereafter. Why is that. Background: All I want to tell bash is to ignore any simple, i.e. one word command. Bash should not remember command lines like `cd`, `pwd`, `history`, etc. My original definition of the `HISTIGNORE` variable looked like this: export HISTIGNORE="!(+(!([[:space:]]))+([[:space:]])+(!([[:space:]])))" I added a `\` backslash character before each `:` colon character because according to the `bash` info pages the latter separates each (extended) shell glob, i.e. pattern from another. Without escaping the single pattern does not have any effect and a simple command still makes it into history. Cheers Tim
Re: Bash's declare -p HISTIGNORE brings bash to a halt! Why?
Hi Chet, hmm ... I simplified the pattern to "+([^[:space:]])". It works on when I let bash expand files but it does not keep bash from adding "word" commands such as "cd", "pwd", etc. My history related settings are as follows: shopt -s extglob declare -x HISTSIZE="1" declare -x HISTFILESIZE="1" declare -x histchars="!^#" declare -x HISTIGNORE="+([^[:space:]])" declare -x HISTCONTROL="ignorespace:ignoredups:erasedups" declare -x HISTTIMEFORMAT="%FT%T " declare -x HISTFILE="/home/tifr/.cache/bash/history" Any ideas as to how to correctly assign the "+([^[:space:]])" pattern to the "HISTIGNORE" variable? By the way I'm setting the history related variables from my ".bash_login" file. That is why I'm exporting them. Thank you very much for your help. Kind regards Tim 2014/1/11 Tim Friske : > Hi, > > executing the following code in GNU bash, Version 4.2.45(1)-release > (x86_64-redhat-linux-gnu), Fedora 19 ... > > shopt -s extglob > export > HISTIGNORE="!(+(!([[\:space\:]]))+([[\:space\:]])+(!([[\:space\:]])))" > declare -p HISTIGNORE > > ... brings bash to a full stop. It does not print a command prompt > hereafter. Why is that. > > Background: > > All I want to tell bash is to ignore any simple, i.e. one word > command. Bash should not remember command lines like `cd`, `pwd`, > `history`, etc. My original definition of the `HISTIGNORE` variable > looked like this: > > export HISTIGNORE="!(+(!([[:space:]]))+([[:space:]])+(!([[:space:]])))" > > I added a `\` backslash character before each `:` colon character > because according to the `bash` info pages the latter separates each > (extended) shell glob, i.e. pattern from another. Without escaping the > single pattern does not have any effect and a simple command still > makes it into history. > > Cheers > Tim
Re: Bash's declare -p HISTIGNORE brings bash to a halt! Why?
Hi Chet, apparently bash does not recognize the ":" colon characters in POSIX character classes when assigned to the "HISTIGNORE" variable. I tried to set the "HISTIGNORE" variable directly from within a non-login, interactive session. But still I cannot convince bash's history with the following definitions: 1.) HISTIGNORE="+([[:word:]])" 2.) HISTIGNORE="+([^[:space:]])" On the other hand such simple definitions work: 1.) HISTIGNORE="+([a-z])" 2.) HISTIGNORE="+([-0-9A-Z_a-z])" Best regards Tim 2014/1/12 Tim Friske : > Hi Chet, > > hmm ... I simplified the pattern to "+([^[:space:]])". It works on > when I let bash expand files but it does not keep bash from adding > "word" commands such as "cd", "pwd", etc. My history related settings > are as follows: > > shopt -s extglob > > declare -x HISTSIZE="1" > declare -x HISTFILESIZE="1" > declare -x histchars="!^#" > declare -x HISTIGNORE="+([^[:space:]])" > declare -x HISTCONTROL="ignorespace:ignoredups:erasedups" > declare -x HISTTIMEFORMAT="%FT%T " > declare -x HISTFILE="/home/tifr/.cache/bash/history" > > Any ideas as to how to correctly assign the "+([^[:space:]])" pattern > to the "HISTIGNORE" variable? By the way I'm setting the history > related variables from my ".bash_login" file. That is why I'm > exporting them. > > Thank you very much for your help. > > Kind regards > Tim > > 2014/1/11 Tim Friske : >> Hi, >> >> executing the following code in GNU bash, Version 4.2.45(1)-release >> (x86_64-redhat-linux-gnu), Fedora 19 ... >> >> shopt -s extglob >> export >> HISTIGNORE="!(+(!([[\:space\:]]))+([[\:space\:]])+(!([[\:space\:]])))" >> declare -p HISTIGNORE >> >> ... brings bash to a full stop. It does not print a command prompt >> hereafter. Why is that. >> >> Background: >> >> All I want to tell bash is to ignore any simple, i.e. one word >> command. Bash should not remember command lines like `cd`, `pwd`, >> `history`, etc. My original definition of the `HISTIGNORE` variable >> looked like this: >> >> export HISTIGNORE="!(+(!([[:space:]]))+([[:space:]])+(!([[:space:]])))" >> >> I added a `\` backslash character before each `:` colon character >> because according to the `bash` info pages the latter separates each >> (extended) shell glob, i.e. pattern from another. Without escaping the >> single pattern does not have any effect and a simple command still >> makes it into history. >> >> Cheers >> Tim
Possible bug when combining Bash's process substitution with HERE-document?
Hi, see my question http://unix.stackexchange.com/questions/137506/how-to-combine-bashs-process-substitution-with-here-document for a description. Could the described behavior be a bug? Kind regards Tim
Re: Possible bug when combining Bash's process substitution with HERE-document?
Hi, first I want to thank you for your help. While searching for an alternative I came up with the following code which does not work when I have the "shopt -os errexit" command line at the top of my script: read -d '' -r foobar <: > On 6/18/14, 4:27 PM, Dan Douglas wrote: >> On Wed, Jun 18, 2014 at 2:49 PM, Chet Ramey wrote: >>> Yes, since bash can parse the same construct without any problems if you >>> use command substitution, it looks like a bug. I'll take a look. >> >> It brings to mind all those unbalanced paren case..esac bugs that >> affected every shell ever. >> I suppose this might qualify as a bug too? > > Yes, with the same fix. > > Chet > > -- > ``The lyf so short, the craft so long to lerne.'' - Chaucer > ``Ars longa, vita brevis'' - Hippocrates > Chet Ramey, ITS, CWRUc...@case.eduhttp://cnswww.cns.cwru.edu/~chet/
Bug or feature: Why does Bash's "printf" define global variables?
Hi, my assumption was that Bash's "printf" builtin implicitly defines a local variable when used inside a function like so: function foobar { printf -v foo bar; } foobar declare -p foo # Prints "bar" from the global "foo" variable. But instead I have to declare the "foo" variable to be a "local" member of the "foobar" function like so: unset -v foo function foobar { local foo=; printf -v foo bar; } foobar declare -p foo # Prints an error message saying that there is no "foo" defined. Cheers Tim
Feature request: Add "import" built-in.
Hi, as I see it the "source" built-in is perfect for embedding a sourced Bash script into the sourcing one while preserving as much of the environment, specifically the positional and special parameters, as possible. What I am missing is the "import" built-in that passes only the explicitly given arguments from the importing to the imported Bash script. I currently emulate the behavior I seek for with the following function: function _import { local -r file="$1" set -- "${@:2}" source "$file" "$@" } For details please see my question and the answers on Unix & Linux Exchange [1]. [1] http://unix.stackexchange.com/questions/151889/why-does-bashs-source-command-behave-differently-when-called-from-a-function Cheers Tim signature.asc Description: OpenPGP digital signature
declare -p my_function does not print its definition. A bug?
Hi, when I define the following function: $ function foo { > echo bar > } and try to run it, I get: $ foo bar but try to print its definition with "declare", I get: $ declare -p foo bash: declare: foo: not found $ declare -pf foo bash: declare: foo: not found $declare -pF foo bash: declare: foo: not found but try to print its definition with "type", I get: $ type foo foo is a function foo () { echo bar } I'm running the above commands in the following environment: * Fedora Linux 20 "Heisenbug" * BASH_VERSION => 4.2.53(1)-release * bash --version => GNU bash, version 4.2.53(1)-release (x86_64-redhat-linux-gnu) Any clue why the declare built-in does not print a function's definition? BR Tim signature.asc Description: OpenPGP digital signature