declare -p my_function does not print its definition. A bug?

2014-10-18 Thread Tim Friske
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


Feature request: Add "import" built-in.

2014-08-24 Thread Tim Friske
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


Bug or feature: Why does Bash's "printf" define global variables?

2014-08-03 Thread Tim Friske
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



Re: Possible bug when combining Bash's process substitution with HERE-document?

2014-06-19 Thread Tim Friske
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/



Possible bug when combining Bash's process substitution with HERE-document?

2014-06-17 Thread Tim Friske
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: Bash's declare -p HISTIGNORE brings bash to a halt! Why?

2014-01-11 Thread Tim Friske
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



Re: Bash's declare -p HISTIGNORE brings bash to a halt! Why?

2014-01-11 Thread 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



Bash's declare -p HISTIGNORE brings bash to a halt! Why?

2014-01-11 Thread 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



Why can't I say "&>&3"? Bug or feature?

2012-12-06 Thread Tim Friske
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



Strange re-initialization of array. Bug or feature?

2012-11-27 Thread Tim Friske
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


How to presence-detect an array variable or subscript thereof with `test -v`?

2012-11-27 Thread Tim Friske
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


Why is not every variable initialized to its data type specific default value upon declaration in Bash?

2012-11-27 Thread Tim Friske
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 initialize a read-only, global, associative array in Bash?

2012-11-26 Thread Tim Friske
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