Re: If the variable has its 'integer' attribute set,

2021-11-21 Thread Greg Wooledge
On Sun, Nov 21, 2021 at 07:18:09PM +, Darac Marjal wrote:
> You probably already know that if you write:
> 
> i = 65
> 
> then several things happen:

Only one thing happens: bash tries to run the command named "i" and
you will almost certainly get an error message saying "command not found".

If you want a variable assignment, you must not have spaces around the =
sign.

i=65

This assigns the string "65" to the variable named i.

> So, that's a very basic method of storing the variable.  At this point,
> we know that the variable "i" equals 65, right? Well, how do we know
> that the variable doesn't hold the character "A", or that it's not an
> array? So, there must be a table somewhere else that tells us "what KIND
> of data is stored in 'i'?".

Bash does not store integer variables.  Ever.  Only string variables.

Using "declare -i" does not change that.  It only makes bash undergo
some weird gyrations every time a new string value is assigned to the
variable in question.  (And overloads the += operator, because life wasn't
confusing enough yet.)

Many people think "Oh, if I use declare -i, bash will store my values
as integers, and arithmetic will become more efficient, because bash won't
have to keep doing string-to-integer conversions all the time."  This is
incorrect.  Everything is stored as a string.



Re: If the variable has its 'integer' attribute set,

2021-11-21 Thread Darac Marjal

On 21/11/2021 01:37, sim sim wrote:
> Hi, all.
> My question may be in the wrong place but I'm already exhausted.
> Started reading https://www.gnu.org/software/bash/manual/bash.pdf.
>
> 3.4 Shell Parameters
> .
> 
> A parameter is set if it has been assigned a value.  The null string
> is a valid value.  Once a variable is set, it may be unset only by
> using the 'unset' builtin command.
>    A variable may be assigned to by a statement of the form
>  NAME=[VALUE]
> If VALUE is not given, the variable is assigned the null string.  All
> VALUEs undergo tilde expansion, parameter and variable expansion,
> command substitution, arithmetic expansion, and quote removal
> (detailed below).  If the variable has its 'integer' attribute set,
> then VALUE is evaluated as an arithmetic expression even if the
> '$((...))' expansion is not used.  
> .........
> ......
> I do not understand  "If the variable has its 'integer' attribute
> set," where the variable has an 'integer' attribute, after all, this
> is not a function?
> I do not ask to explain in detail, because it is long and I will not
> understand because of my poor English, but if you can just write a
> simple variable for:
>  name=[value]
> where "If the variable has its 'integer' attribute set",
> for example it will help a lot. This manual is difficult for a
> beginner to read. The same concept in different places denotes: either
> an attribute or a parameter or an option.
> And advise a smart forum on this topic, where you can ask questions,
> Google found trash.

The way I would explain it is to assume that bash stores variables with
"data" and "metadata" separately.

You probably already know that if you write:

i = 65

then several things happen:

* a block of memory is allocated

* the address of the allocated memory is stored somewhere, and a
reference to that address is associated with the variable "i"

* The value "65" is stored in that memory location

So, that's a very basic method of storing the variable.  At this point,
we know that the variable "i" equals 65, right? Well, how do we know
that the variable doesn't hold the character "A", or that it's not an
array? So, there must be a table somewhere else that tells us "what KIND
of data is stored in 'i'?".

From a naive point of view, we might use an enumeration for the type (if
the type is 1 it's an integer, if it's 2 it's a string, if it's 3 it's
an array and so on), but the authors of bash, for whatever reason, seem
to use type flags. Perhaps a variable can be an integer *and* a string?
I'm not sure.

In summary, though, I would read "If the variable has its 'integer'
attribute set" as synonymous with "If the variable is declared an
integer". The bit to be careful about is that the value is NOT evaluated
as an arithmetic if the variable merely LOOKS like an integer (e.g. the
string "65").


> Thanks,
> Sim.


OpenPGP_signature
Description: OpenPGP digital signature


Re: If the variable has its 'integer' attribute set,

2021-11-20 Thread Greg Wooledge
On Sun, Nov 21, 2021 at 01:37:14AM +, sim sim wrote:
> I do not understand  "If the variable has its 'integer' attribute set," where 
> the variable has an 'integer' attribute, after all, this is not a function?

They're talking about "declare -i".  Which is really a stupid thing
and I wish it didn't exist, but it does, and people are silly enough
to use it, and I cannot stop them.

For those who don't understand the context of the question, this is
about bash, and variables in bash.

All variables in bash hold string values.  Even if you use "declare -i",
the value that is stored in memory is a string.  What "declare -i" does
is make it so that when you assign new strings to the variable, dark
magic occurs.  The value that gets assigned will be interpreted by the
shell's math context parser, and the result will be a value that looks
like a number, or else an error.

unicorn:~$ bash
unicorn:~$ declare -i foo
unicorn:~$ foo=bar
unicorn:~$ declare -p foo
declare -i foo="0"

So... what happened here?  We tried to assign the string "bar" to a
variable with the "-i" flag set.  Since bar doesn't look like a number,
it was sent into the math context parser.  The math context parser saw
that "bar" looks like a variable name, so it recursively evaluated "bar"
in a math context, retrieve the value from the variable "bar".  Which
did not exist.  So that value was assigned as "0".  Which is a string that
looks like a number.  Because, as I said, all bash variables hold strings.

unicorn:~$ bar='hello world'
unicorn:~$ foo=bar
bash: hello world: syntax error in expression (error token is "world")

Here, we got an error, because "hello world" could not be evaluated by
the shell's math parser.

unicorn:~$ bar=7*9
unicorn:~$ foo=bar
unicorn:~$ declare -p foo bar
declare -i foo="63"
declare -- bar="7*9"

Here, bar which is an ordinary value holds the string value "7*9", which
happens to be a valid expression in the eyes of the shell's math parser.
When we assigned "bar" to "foo", which has the "-i" flag set, the string
value was fed to the math parser, and "7" and "9" were temporarily
turned into integers, and a multiplication was performed, and then the
resulting number 63 was turned back into a string, and the string "63"
was stored in "foo".

Why people think this is a good idea is utterly beyond me.  I can only
advise you never to use this thing.  It's confusing and dumb.  If you want
to perform arithmetic while assigning a value to a variable, I advise
you to use an *explicit* arithmetic expression:

foo=$(( math stuff here ))

That way you can see what's happening when you read the script, and there
won't be as many surprises.

Bash is full of enough landmines without introducing more.



If the variable has its 'integer' attribute set,

2021-11-20 Thread sim sim
Hi, all.
My question may be in the wrong place but I'm already exhausted. Started 
reading https://www.gnu.org/software/bash/manual/bash.pdf.

3.4 Shell Parameters
.

A parameter is set if it has been assigned a value.  The null string is a valid 
value.  Once a variable is set, it may be unset only by using the 'unset' 
builtin command.
   A variable may be assigned to by a statement of the form
 NAME=[VALUE]
If VALUE is not given, the variable is assigned the null string.  All VALUEs 
undergo tilde expansion, parameter and variable expansion, command 
substitution, arithmetic expansion, and quote removal (detailed below).  If the 
variable has its 'integer' attribute set, then VALUE is evaluated as an 
arithmetic expression even if the '$((...))' expansion is not used.  
.
..
I do not understand  "If the variable has its 'integer' attribute set," where 
the variable has an 'integer' attribute, after all, this is not a function?
I do not ask to explain in detail, because it is long and I will not understand 
because of my poor English, but if you can just write a simple variable for:
 name=[value] 
where "If the variable has its 'integer' attribute set",
for example it will help a lot. This manual is difficult for a beginner to 
read. The same concept in different places denotes: either an attribute or a 
parameter or an option.
And advise a smart forum on this topic, where you can ask questions, Google 
found trash.
Thanks,
Sim.