fozzybear
fozzybear

Reputation: 155

bash: declare -i behavior unclear

I'd need clarification about some aspects of declare -i:

As stated on gnu.org:

6.5 Shell Arithmetic

[...]The value of a variable is evaluated as an arithmetic expression when it is referenced, or when a variable which has been given the integer attribute using ‘declare -i’ is assigned a value. A null value evaluates to 0.[...] A leading ‘0x’ or ‘0X’ denotes hexadecimal.

Why does declare -i hex1=x1 not yield an error and obviously assigns null -> 0 instead? Expectation would be, that an error like 'invalid option' is thrown, since the command argument obviously cannot be successfully evaluated.

For a valid declared hex number, echo obviously prints a converted decimal value instead of the hex number, as does printf '%s', whereas printf '%x' prints the originally declared hex value:

unset -v hex1
declare -i hex1="0x10"
echo -e $hex1
-> '16'
printf '%x' $hex1
-> '10'

I can also verify the var's int nature:

declare -p hex1
> 'declare -i hex1="16"'

Problem occurs, if I want to check the int nature after referencing hex1 per name reference (e. g. from a function's argument):

declare -n hexRef=hex1

Using the parameter expansion syntax will evaluate the var to its hex value and fail:

declare -p $hexRef
> '-bash: declare: 16: not found'

Using the var name instead will show the reference's declaration, which is not helping either:

declare -p hexRef
> 'declare -n hexRef="hex1"'

Writing these lines, I've found a partial solution to this problem, which reveals the referenced var's int nature:

[[ "${hexRef@A}" == 'declare -i'* ]] && echo INT
> 'declare -i hex1='16''

This still obfuscates the actual hex nature of the var, though, due to its evaluation to a decimal value, in the parameter expansion with operator @A. Can the original var's hex value be preserved in referencing, like shown above, or somehow recovered afterwards?

Or is there another way of directly checking for the var's hex nature?

Checking for [[:xdigit:]] doesn't work of course, since it only narrows the RegEx down to digits specified for hex numbers, not the type:

declare -i noHex=10; [[ $noHex =~ ^[[:xdigit:]]+$ ]] && echo HEX
-> HEX (only hex digits, not hex/int type)

Upvotes: 0

Views: 54

Answers (0)

Related Questions