414 lines
33 KiB
Plaintext
414 lines
33 KiB
Plaintext
|
|
Episode: 1951
|
||
|
|
Title: HPR1951: Some additional Bash tips
|
||
|
|
Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr1951/hpr1951.mp3
|
||
|
|
Transcribed: 2025-10-18 11:46:27
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
This is HPR episode 1951 entitled Sum additional bash tips and is part of the series bash
|
||
|
|
cryptying.
|
||
|
|
It is hosted by Dave Morris and is about 40 minutes long.
|
||
|
|
The summary is more about expansion in bash, this time arithmetic expansion.
|
||
|
|
This episode of HPR is brought to you by an honesthost.com.
|
||
|
|
Get 15% discount on all shared hosting with the offer code HPR15 that's HPR15.
|
||
|
|
Get your web hosting that's honest and fair at An Honesthost.com.
|
||
|
|
Hello everyone, this is Dave Morris.
|
||
|
|
Today's episode is another one in my series bash, continuing the subject of expansion.
|
||
|
|
I've called it some additional bash tips.
|
||
|
|
I wish now I'd numbered these ones because might have made more sense, but never mind.
|
||
|
|
So last episode in this mini series was 1903 and we looked at the various types of expansion
|
||
|
|
that occur when a bash script or pipeline on the command line whatever is being executed.
|
||
|
|
And I listed all the various types of expansion.
|
||
|
|
We got as far as looking at tilde expansion 1903 and then command substitution.
|
||
|
|
So today, well before I say that, there are three more, possibly four more items to
|
||
|
|
to cover in this list, arithmetic expansion is what I'm looking at today and it might
|
||
|
|
take another two episodes to cover the rest.
|
||
|
|
I don't know.
|
||
|
|
These things tend to be longer than I expect them to be when I come to do them.
|
||
|
|
One small note while I'm on the subject of these notes, I've got long show notes for
|
||
|
|
this episode of course.
|
||
|
|
So my side note is that I have changed the way I'm doing my examples.
|
||
|
|
In previous notes, I have indicated the command to type and the result of typing the command
|
||
|
|
in a different way.
|
||
|
|
The result I've put a minus and a greater than in front of it to show what it is.
|
||
|
|
This time around, I'm going to show the command as if it was being typed to a prompt and
|
||
|
|
the prompt would be a dollar prompt.
|
||
|
|
So if you see a line beginning dollar space and then a command, that's what you would type.
|
||
|
|
And the stuff that follows would be what comes back from typing the command.
|
||
|
|
In most cases, my examples produce some sort of output because I'm using them to demonstrate
|
||
|
|
an idea and so forth.
|
||
|
|
I think this method I'm using from now on is probably less ambiguous than the one before.
|
||
|
|
It was pointed out to me that the previous way of doing it was a bit hard to follow in
|
||
|
|
all cases.
|
||
|
|
Anyway, getting on with the actual subject, arithmetic expansion.
|
||
|
|
So this is a type of expansion that takes an arithmetic expression and returns the result.
|
||
|
|
So you can see, the first example here shows that you need to start such an expansion
|
||
|
|
with a dollar sign, two open parentheses, the expression and then two closed parentheses.
|
||
|
|
So I've given an actual example which is dollar space, echo, space, dollar, double open
|
||
|
|
parentheses, 42 slash five, close parentheses twice.
|
||
|
|
What that's doing is it's dividing 42 by five and the answer comes out as eight.
|
||
|
|
Now this is integer arithmetic as you will have gathered from that result.
|
||
|
|
The fractional part is thrown away.
|
||
|
|
I thought it was worth putting in at this point that if you really want to do full fractional
|
||
|
|
result to this, then you can use the BC command.
|
||
|
|
This was covered in Dan Washco's Linux in the Shell series, which was done as HBR show
|
||
|
|
number one, two, two.
|
||
|
|
And there's an example showing, I won't read these all out in huge detail, but I'll summarize
|
||
|
|
them as I go.
|
||
|
|
Essentially you need to use echo to prepare an expression which you then pipe to BC.
|
||
|
|
So the example shows echo followed by in quotes, double quotes, scale equals two, semicolon.
|
||
|
|
BC can take multiple commands to it, it's a whole language in itself.
|
||
|
|
So semicolon, as I said, space 42 slash five, close quote, then a space, not necessarily,
|
||
|
|
but that's what I've got, vertical bar, which is the pipe symbol, space, BC.
|
||
|
|
So if you do that, it puts that, it sends that expression from which is really a little
|
||
|
|
program to BC and you get back 8.40.
|
||
|
|
The scale equals two bits says to BC that you want two decimal places in your result,
|
||
|
|
but if fault it returns you an integer result.
|
||
|
|
In the example I showed, I used echo to report back the result of the expression I just
|
||
|
|
explained to you and I put it inside a command substitution.
|
||
|
|
That was slightly silly, though it was just to make the point really, if you were doing
|
||
|
|
this for real in a script or something, you'd probably set a variable to the result of
|
||
|
|
that echo into BC pipeline.
|
||
|
|
And I've got an example there that shows how you would do that and then you'd echo that
|
||
|
|
variable.
|
||
|
|
So when you're doing arithmetic expansion in bash, the expressions that you use don't
|
||
|
|
just have to contain numbers, they can also contain bash variables.
|
||
|
|
Usually when you do this, you use just the plain name of the variable.
|
||
|
|
You don't put a dollar on the front.
|
||
|
|
Remember that we looked at this way back in this series where if you put a dollar in
|
||
|
|
front of the variable name, that means substitute in the contents of that variable.
|
||
|
|
So I've shown in my example X being set to 42, then an echo space dollar to open parentheses
|
||
|
|
X slash 5, X divided by 5, close parentheses, close parentheses and the answer comes back
|
||
|
|
as 8.
|
||
|
|
Now if you put a dollar on front of that egg, you've got the same result.
|
||
|
|
There are however potential pitfalls of doing this.
|
||
|
|
The expression inside the double parentheses is subject to variable expansion, as you
|
||
|
|
might expect.
|
||
|
|
So dollar X means expand the contents of X.
|
||
|
|
So in the example I've just cited, it would, the contents of 42, so it would have, would
|
||
|
|
have substituted 42 in and the result would have been the expression 42 slash 5, 42 divided
|
||
|
|
by 5.
|
||
|
|
That's okay, but it's, there are some potential pitfalls that I'll come on to a bit later
|
||
|
|
on.
|
||
|
|
Now if a variable is null or unset and we're back to using it without the leading dollar,
|
||
|
|
then it, it value X to 0, it's interpreted as 0 by bash.
|
||
|
|
If it was empty and you use the dollar to substitute it, you would end up most likely with an invalid
|
||
|
|
expression.
|
||
|
|
The value of a variable is always interpreted as an integer.
|
||
|
|
If it's not actually an integer but it's say for example a text string, then it's treated
|
||
|
|
as 0.
|
||
|
|
I didn't find this documented actually, so I'm mentioning it here because this was the
|
||
|
|
result of doing a little bit of experimentation.
|
||
|
|
I show an example where I set a variable called STR, short for string equal to an A in double
|
||
|
|
quotes.
|
||
|
|
I echo using arithmetic expansion dollar open parenthesis, open parenthesis, STR times
|
||
|
|
2, close parenthesis twice, of course, and the answer comes back as 0.
|
||
|
|
So it's taken that letter A has treated it as 2, as 0.
|
||
|
|
I mean multiplied it by 2 and of course the answer is 0.
|
||
|
|
And the second example in this group is setting it to the string 0X capital A in quotes
|
||
|
|
again.
|
||
|
|
Now, if you put that into the arithmetic expansion expression, then the answer is 20.
|
||
|
|
The reason for that is that 0X capital A is interpreted as a non decimal number.
|
||
|
|
So I go on to explain a bit about this now in the notes.
|
||
|
|
So there are a whole range of non decimal numerical constants available in bash.
|
||
|
|
So any number that begins with a 0 and is followed by digits is taken to be octal.
|
||
|
|
Hexed decimal numbers are denoted by a leading 0 lowercase X or 0 capital X.
|
||
|
|
So my previous example was hex A, which is 10, multiplying that by 2, gives me 20.
|
||
|
|
Be aware that the way in which octal constants are written, that is that leading 0, followed
|
||
|
|
by digits.
|
||
|
|
It can lead to unexpected outcomes.
|
||
|
|
I mention this because I've been bitten by this many times.
|
||
|
|
Well, I was anywhere in the early days when it just didn't seem like a logical thing
|
||
|
|
to do.
|
||
|
|
So my example here is quite long, a bit long to read out, but just to summarize it, I start
|
||
|
|
off by setting a variable X to the number 010.
|
||
|
|
And then echoing it in a arithmetic expansion expression.
|
||
|
|
So dollar, open parenthesis, open parenthesis, X, closed parenthesis, closed parenthesis.
|
||
|
|
The answer comes back as 8.
|
||
|
|
The reason for that, I'm sure you've worked that out, is that it's interpreted as an
|
||
|
|
octal number.
|
||
|
|
So an octal 10 is 8 in decimal.
|
||
|
|
And it's always reporting these back as decimal, of course.
|
||
|
|
So then I show an example where I might have typed the number 018 and set that into a
|
||
|
|
variable.
|
||
|
|
And then tried to echo it back again as a number using the arithmetic substitution expansion
|
||
|
|
thing.
|
||
|
|
And I get an error back from bash saying that 018 value 2 great for base.
|
||
|
|
So what it's saying is this, I'm interpreting this as an octal number, you kind of 8's in
|
||
|
|
octal.
|
||
|
|
You only go from 0 to 7 in the digits.
|
||
|
|
So I also showed how you could easily fall into that trap by using print f, print f minus
|
||
|
|
v, followed by X.
|
||
|
|
What that does is it uses print f to format text or a number or whatever and put it into
|
||
|
|
the variable X.
|
||
|
|
And in the format string, I've got open double quotes, percent 0 3d.
|
||
|
|
That's why I'm saying you want to print a number.
|
||
|
|
You want it to be three digits wide.
|
||
|
|
And you want leading zeros, back size aim for new liner when it's done it.
|
||
|
|
And then close double quotes and give it the number 19, decimal 19.
|
||
|
|
So processing that, the print f will produce 019 and putting that into an echo followed
|
||
|
|
by an arithmetic substitution will produce similar sort of error to the one I just mentioned
|
||
|
|
because 019, treated as an octal number is illegal.
|
||
|
|
You can see how easy it might be to generate such numbers and then try and process them
|
||
|
|
in this way.
|
||
|
|
And suddenly you find why is this why is 19 illegal and forget that that leading zero means
|
||
|
|
it's interpretive as octal.
|
||
|
|
There's also a complete system within bash of defining numbers with bases between 2 and
|
||
|
|
64.
|
||
|
|
And to do that, you put in a base, a numeric base, followed by a hash mark, followed
|
||
|
|
by a number in that base.
|
||
|
|
So if the numeric base and then the hash is emitted, then it's assumed that it's a base
|
||
|
|
ten number.
|
||
|
|
That is a decimal number.
|
||
|
|
Or it could also be an octal number if it begins with a zero or a hexadecimal number
|
||
|
|
if it begins with zero x.
|
||
|
|
The number that follows the base hash sequence is, can use characters to represent the different
|
||
|
|
digits that are possible in the different bases.
|
||
|
|
And same way as if you're typing in a hexadecimal number, like one we saw before, the hexadecimal
|
||
|
|
A is actually representation of decimal ten.
|
||
|
|
So the characters that you can use in bash are the letters lowercase A to lowercase Z
|
||
|
|
and uppercase A to uppercase Z and the at sign and the underscore sign.
|
||
|
|
The reason I've spelled them out so clearly, hopefully anyway, is that they're not sequential
|
||
|
|
through the ASCII set, but it makes sense to do it that way.
|
||
|
|
Now one of the things I discovered, it's not well documented in the man pages, but messing
|
||
|
|
around with it, I discovered that the context in which these number formats with the base
|
||
|
|
thingy are understood by bash are a bit limited.
|
||
|
|
So I show an example where I'm setting x equal to 16 hash capital F. So that's, that's
|
||
|
|
why I'm representing a hexadecimal number F. So I then try and echo that, just echoing
|
||
|
|
dollar x. And of course, well, not of course, but what I get back is the number, the sequence,
|
||
|
|
the strings 16 hash F. So bash has not converted them or treated it like string.
|
||
|
|
There's another example as well which sets x to 0 x F, which is using the other format
|
||
|
|
for the representing hexadecimal, echo that and you get 0 x F. So it's treating them
|
||
|
|
as string. There are other ways, actually this is quite a big subject, which I'm not covering
|
||
|
|
here particularly deeply. There are other cases where you can force bash to actually treat
|
||
|
|
these consonants as the numbers they represent. And there's a declare verb, you can, as
|
||
|
|
example here, it shows declare minus i, followed by a variable I've called i i with two capital
|
||
|
|
i's, and set that to equal to 16 hash F. So what that's actually done is it's declared
|
||
|
|
this variable i i, in capitals. Why did I choose this? It's really hard to speak, it's
|
||
|
|
a discrapping word. Anyway, I should must remember this in the future. It's declared it
|
||
|
|
explicitly. Usually these things are done implicitly. It's declared it and said it's
|
||
|
|
an integer. It's only to hold integers. So setting it to that value, 16 hash F says it's
|
||
|
|
an integer put this value in which you understand don't you bash. And then if you echo that
|
||
|
|
variable you get back the answer 15. So it has in this case interpreted it. I think that's
|
||
|
|
because the variable is declared as an integer type variable as opposed to the usual type
|
||
|
|
which which are sort of general purpose and don't have any specific attributes to them.
|
||
|
|
So bash doesn't know when you're setting them, whether you're trying to set a numeric
|
||
|
|
value or a string. There's also a let command, let, which is all can also be used for setting
|
||
|
|
variables. So I show an example where I use let space x equals 16 hash F then echo dollar
|
||
|
|
x and get back the answer 15. So that's another case where this has interpreted the base hash
|
||
|
|
number thing when setting the value. Now these things like declare and let and some other
|
||
|
|
things are all part of what tends to be called shallow arithmetic. And although we're we're
|
||
|
|
looking at this to some degree in this show, we're not going to go into the into a lot of detail.
|
||
|
|
I'm thinking that maybe I need to talk more about this subject later on in the in the series.
|
||
|
|
Now if you do the next example here which is setting x to just plain x equals 16 hash F then
|
||
|
|
if you echo the the contents of x through the arithmetic expansion syntax dollar open
|
||
|
|
parenthesis open parenthesis x close parenthesis close parenthesis you get back 15. So the the
|
||
|
|
arithmetic expansion syntax does force the correct interpretation to take place. I digress a little
|
||
|
|
bit at this point in my notes to demonstrate a little bit of bash a very small script that
|
||
|
|
could be used to examine the decimal values that you get with different sorts of notation.
|
||
|
|
I don't did I say the the types of the bases that you're allowed yes I did the bases that you're
|
||
|
|
allowed vary from two to 64 and what I thought I'd do is just demonstrate numbers to base 64
|
||
|
|
and just just run through them or all the single digit numbers in that in that range just to show
|
||
|
|
how you can visualize them. So I've got a for loop what I've done here is I've written it out as if
|
||
|
|
it's a the sort of script that you put in a file so it starts with a hash exclamation mark line
|
||
|
|
which hopefully you can you can see I won't read it out then there's a for loop which is setting a
|
||
|
|
variable x so it's a for x in and then following the inward there are a bunch of expressions and
|
||
|
|
these are brace expansions so I've put in there open brace zero dot not nine close brace space open
|
||
|
|
brace locate a dot dot z locate z of course close brace space open brace capital A dot dot capital
|
||
|
|
z close brace then an at space then an underscore semicolon space do so what that loop is saying is
|
||
|
|
that to set x to all of the values from zero through nine locate a through z uppercase a through
|
||
|
|
uppercase z at sign and underscore and then the next line says n equals and then in quotes 64 hash
|
||
|
|
dollar x close quotes double quotes so what that's done is it's made a base 64 expression constant
|
||
|
|
really out of the the variable x then we echo the string in double quotes dollar n so we want
|
||
|
|
to see what n is actually set to which will be just be that string that we just used equals dollar
|
||
|
|
open parenthesis open parenthesis n close parenthesis close parenthesis close double quotes so
|
||
|
|
you should therefore get things like and there's some examples in the notes 64 hash zero equals
|
||
|
|
not too surprisingly but more interestingly 64 hash capital Y equals 60 all the way to 64 hash
|
||
|
|
underscore equals 63 so a number to base 64 written as 64 hash underscore actually means decimal 63
|
||
|
|
so it's actually quite a big subject which I've digressed into here but we could do a lot more about
|
||
|
|
this as I've already said I'll stop at this point so let's look at what can actually go in between
|
||
|
|
these double parenthesis in an arithmetic expansion it's written down as being an arithmetic
|
||
|
|
expression and it's documented in the bash man page under the heading arithmetic evaluation
|
||
|
|
partly because the same syntax is used in the whole larger subject of shell shell arithmetic
|
||
|
|
so I've included that particular piece of the man page in the notes for for your edification
|
||
|
|
it's a big man page so it's quite it takes fabric to scroll to I thought it might be useful if you
|
||
|
|
had it in these notes so you can do a lot of quite useful interesting things in an arithmetic
|
||
|
|
expression in fact there's a lot to be said here which I could go on and on about but I'm trying
|
||
|
|
to restrict myself to a subset of it but I wanted to to cover some of the elements of it just to
|
||
|
|
give you a better understanding of it first of all we'll deal with pre and post increment and
|
||
|
|
decrement now if you look at the the man page you'll see this heading and they're not really very
|
||
|
|
well explained it's assuming what they mean the operators here increment or decrement the
|
||
|
|
contents of a variable by one and the pre and post effect remember it's pre and post increment
|
||
|
|
pre and post bit says whether the operation is performed before or after the value is used so
|
||
|
|
I've listed a bunch of examples hopefully to make this clearer so my example sets a variable which
|
||
|
|
I've called vowel the al equal to 87 then is followed by an echo where the echo is a quoted
|
||
|
|
double quoted string and inside the string is dollar open parenthesis open parenthesis plus
|
||
|
|
plus vowel close parenthesis close parenthesis and then space dollar vowel so the idea was that the
|
||
|
|
arithmetic expansion would be used and it would use one of these pre and post things and then you'd
|
||
|
|
see the actual value thereafter because it's actually changing this variable okay so take that first
|
||
|
|
example where we're using plus plus vowel inside the arithmetic expansion what that saying is
|
||
|
|
increment this value before you display it so started out as 87 we incremented and it becomes 88
|
||
|
|
we see it in the output from the echo then we look at the contents of vowel after that express
|
||
|
|
and spin executed and it's 88 we know that not too surprising so the next example uses a pre
|
||
|
|
decrement which is minus minus vowel so it's all right we just said it to 88 so the answer comes
|
||
|
|
back as 87 and that that means that the vowel itself has been changed to that value and we show
|
||
|
|
that as part of the echo it's the same same line but with different operations inside so the
|
||
|
|
third one we're using vowel of course again but this time is a vowel plus plus so that's a
|
||
|
|
post decrement the post increment sorry I'm getting confused now so it was 87 so when the result
|
||
|
|
of vowel plus plus is we we get back the value of vowel before it was incremented so we see 87
|
||
|
|
and then afterwards the variable vowel contains 88 so the result of the echo is 87 followed by 88
|
||
|
|
and the last example is similar but we're using a post decrement so we know that vowel is currently
|
||
|
|
88 in the example so we do vowel minus minus and then we show the contents of vowel so the answers
|
||
|
|
we get back are 88 and 87 so it was 88 when it went into the vowel minus minus post decrement
|
||
|
|
and then it was reduced to 87 so I'm showing the contents of vowel results in 87 it's actually
|
||
|
|
a bit confusing to hear read out think if you if you can look at the at the example you might
|
||
|
|
find that explains things better now the pre and post increment and decrement operators need variables
|
||
|
|
not number because it's all about taking a variable doing the thing to it and saving that
|
||
|
|
the result so I show another example of how if we set a variable we call in my var equal to 128
|
||
|
|
then we echo in dollar open parenthesis open parenthesis plus plus my var closed parenthesis
|
||
|
|
closed parenthesis we get back 129 so it's it's incremented the the result and has reported what
|
||
|
|
happened now if instead of that we'd put a dollar in front of my var then it would have caused
|
||
|
|
the contents of my var to be substituted rather than the name of the variable so that can it's either
|
||
|
|
you know that doesn't it's either syntactically invalid to do it to do that or it can lead us to
|
||
|
|
weird effect so I show an example where I use echo and then an arithmetic expansion using dollar
|
||
|
|
my var minus my and I get back a bash error saying syntax error operand expected and it's saying
|
||
|
|
you know what I see is 129 minus minus that means nothing the reason why it can lead to one
|
||
|
|
wanted effect is that if you are doing a a pre decrement for example my next example shows
|
||
|
|
my var being set to 128 and then we use the expression minus minus dollar my var and the answer
|
||
|
|
we get back is 128 so what's happened there is that the substitution has resulted in the sequence
|
||
|
|
minus minus 1 2 8 what that actually means is negative 1 2 8 then made negative so in other words
|
||
|
|
the two two minus signs cancel one another out so you can see there's loads of scope for a confusion
|
||
|
|
if you do this so the reason I'm hammering on about this is because if you if you're into this sort
|
||
|
|
of stuff you really need to bear in mind which of the operators work on the variable names and
|
||
|
|
which work on or can work on numbers so my examples skip around a bit between the the various
|
||
|
|
operators a treat new unreminus neck which is just putting a minus sign in front of the variable
|
||
|
|
and it just changes the sign of it so my example shows a minor in being set to 16 and then we use
|
||
|
|
minus int and the answer we get is minus 16. Exponentiation is the next example we're assuming
|
||
|
|
the int is available throughout all these examples and we use the expression int star star two so
|
||
|
|
that means raise the power of two remember int was 16 so 16th power two is 256 16th squared in
|
||
|
|
other words 16th squared is 256 now the expressions that you can place inside this dollar open
|
||
|
|
parenthesis open parenthesis closed parenthesis closed parenthesis arithmetic expansion thing
|
||
|
|
can be any arbitrary of any arbitrary complexity so I show an example next where I'm using int
|
||
|
|
to the power of two so it's int star star two plus three then I want to get the remainder after
|
||
|
|
division by five so I needed to put the int to the power of two plus three in parenthesis otherwise
|
||
|
|
the percent operator the the remainder operator would apply to the three rather than to the
|
||
|
|
result of that expression so I needed parenthesis there and that's as you would expect it to be
|
||
|
|
I go on to talk about the bitwise shift and bitwise or features operators I guess they would be
|
||
|
|
so here my example is using int and then the bitwise shift to the right is two greater than signs
|
||
|
|
followed by one which means shift the contents of int by one bit to the right so 16 is shifted to
|
||
|
|
the right by one which is the equivalent of division by two the answer is eight and I talk about
|
||
|
|
how you would visualize that in binary 16 is binary one zero zero zero zero as one followed by four
|
||
|
|
zeros shifting it to the right once returns one zero zero zero one followed by three zero which is
|
||
|
|
binary eight decimal eight I mean next one is int shifted to the left one place so shifting
|
||
|
|
16 to the left once returns a one in binary turns returns a one followed by five zeros which is
|
||
|
|
32 in decimal and I'll see answer you get then I show how you could use bitwise or where take int
|
||
|
|
shift it left by one and then or it with eight so 16 shifted left one is 32 binary oring
|
||
|
|
eight to it is in binary it is one followed by five zeros or with zero one followed by three zero
|
||
|
|
and the answer to that is one zero one zero zero zero which is decimal 40 it's actually 32 plus eight
|
||
|
|
I do the same thing using hexadecimal so I've got a print f and the print f is using the percent
|
||
|
|
hash x format which says print the number that you've been given in hexadecimal format with a zero
|
||
|
|
x on the front of it fact it's a lowercase x means you get zero lowercase x then there's a back
|
||
|
|
slash n which causes a new line to be generated and the expression I'm feeding it is another
|
||
|
|
arithmetic expansion in fact it's the one we just saw is the one that contains int shift int
|
||
|
|
shifted left one place ord with eight and the result you get back is hexadecimal 2828 I
|
||
|
|
suppose you'd be best to call it so you can visualize that in binary as zero zero one zero for
|
||
|
|
for the two and zero sorry one zero zero zero which represents the eight so it's the same
|
||
|
|
as the previous answer it's just that hex is a more helpful way of visualizing it in this list
|
||
|
|
there's also a conditional operator and I thought I should have a go at explaining that so
|
||
|
|
conditional operator in bash is similar to the sort of things you see in other languages in
|
||
|
|
c and so forth but it only operates with integer values its layout is an expression which has
|
||
|
|
to return a value which can be interpreted as true or false so zero or one followed by a question
|
||
|
|
mark followed by another expression which returns a numeric value a colon and a third expression
|
||
|
|
so if the the first expression returns true then the second expression in the list is returned
|
||
|
|
if it returns false then third expression in the list is returned so my example is moderately
|
||
|
|
complicated what I've got is really a little script except it's not written out as a script it's
|
||
|
|
just a bunch of commands a variable my var equal to the result of the expression
|
||
|
|
ink shifted left three times three three places and that's in an arithmetic expression
|
||
|
|
so what it is it's the same as multiplying it by two three times so the answer will be 128
|
||
|
|
that's then followed by an array declaration msg message equals open parenthesis then there are
|
||
|
|
three strings separated by spaces close parenthesis and the strings are in single quotes under 100
|
||
|
|
between 100 and 200 is the second string and the third string is over 200 third line is range
|
||
|
|
equals and here we come to the conditional operator so range is being set to an arithmetic
|
||
|
|
expansion expression which is dollar open parenthesis open parenthesis my var greater than 100 so
|
||
|
|
that's the first expression of the triple my var greater than 100 and so we're asking is my
|
||
|
|
var greater than 100 follow that with the question mark then the first expression that follows that
|
||
|
|
the one that will be executed if the if the value is is true is another is another conditional
|
||
|
|
operator which I'll come back to in a minute the one that is returned if its false is just a symbol
|
||
|
|
playing zero so that's all close with two closing parenthesis so that second internal expression
|
||
|
|
second expression in this conditional operator is another arithmetic expansion which is a dollar
|
||
|
|
open parenthesis open parenthesis here we have first expression in the triple is my var greater
|
||
|
|
than 200 the question mark followed by two colon one so the whole thing is is saying if my var is
|
||
|
|
greater than 100 then the second arithmetic expansion is used which then test to see if my
|
||
|
|
var is greater than 200 if it is result returned is two otherwise result returned is one and if the
|
||
|
|
original thing was less than 100 then zero is returned so the result of all that is that
|
||
|
|
range is set to zero meaning that my var is under 100 one means between 102 and two means over
|
||
|
|
200 so the echo which follows in this example consists of the string and double quotes my var equals
|
||
|
|
dollar my var so we're going to see what what the current value of my var is we comma space
|
||
|
|
range equals dollar range I'm going to want to see what range came back from the value came back
|
||
|
|
from that that horrible expression finally message colon space and then that's followed by dollar
|
||
|
|
open brace msg square brackets dollar range close square brackets close brace close double quotes
|
||
|
|
so that you will recall hopefully is the way that you get an array element in bash and we're
|
||
|
|
getting an element out of the array msg and we're indexing it by whatever value came back from
|
||
|
|
the computation of range so my example I show what actually is returned and we get back my var
|
||
|
|
equals 128 not surprisingly we knew that was what was going to be range equals one well 128 is
|
||
|
|
between 100 and 200 and the message that's returned the contents of that msg array is the string
|
||
|
|
between 100 and 200 so it's quite a contrived example but it um hopefully conveys the sort of
|
||
|
|
thing that can be done with this type of type of thing why would you want to do it this way I
|
||
|
|
suppose I tend to do this but um but I mean you could make it a lot more explicit by using if then
|
||
|
|
type structuring in your script but um it's it's it's it's this thing exists and it's nice to use
|
||
|
|
I find anyway I follow this with another example of that sequence of setting my var setting range
|
||
|
|
and echoing result of everything but this time I changed my var to int shifted four places to the
|
||
|
|
left in other words it's 16 times 2 to the 4 which is 256 then we recalculate range we don't
|
||
|
|
need to reset msg because it's already been set previously recalculate range use it in the same
|
||
|
|
echo as we did last time we get back my var equals 256 range equals to message over 200 so like I
|
||
|
|
said these are these are somewhat contrived and maybe not they're not all that robust it's easy
|
||
|
|
to break this but uh you can see the principle you could use this to to make make a script do something
|
||
|
|
classifying numbers in various ways all sorts of things you could do I want to look at finally in
|
||
|
|
this talk I wanted to look at assignment use of assignment in arithmetic expressions you can set
|
||
|
|
variables within these expressions and there are some other assignment operators available to you
|
||
|
|
if you do that so I've got things got my first example a group of examples is setting x equal to
|
||
|
|
and here's a base expression so one two hash two zero so that's the number two zero in base 12
|
||
|
|
and it's in an echo so echoing that back comes back to 24 so two zero to base 12 is decimal 24
|
||
|
|
and it's also set x to that value it's set it to it and also returned the value because there was an
|
||
|
|
echo then the next echo is x is echoing x star equals two so what that's saying in this assignment
|
||
|
|
is set x to the result of multiplying x by two which since it was 24 is 48 and x will now be 48
|
||
|
|
the final one do an echo all of these are in arithmetic expansion expressions which I'm not
|
||
|
|
reading at all the dollar princess business because I'm sure you're with me so the last one is x
|
||
|
|
percent equals five so that's a remainder type thing and it's saying set x to the remainder
|
||
|
|
of x divided by five which since it's 48 is three okay so I spelled this out in the in the notes
|
||
|
|
x is set to two zero base 12 and so on and so forth then the next example is demonstrating how
|
||
|
|
you can set things to binary values if you want to so I'm using b equals two hash one zero zero zero
|
||
|
|
so the if you put that into an echo then you get back eight because that's binary one followed
|
||
|
|
by zero three zeros is eight so that's one zero zero zero zero to the base two zero expressing it
|
||
|
|
then the next echo it uses b vertical bar equals that's that's using a bitwise or assignment so
|
||
|
|
what that means is b is it is to be set to itself or with the expression which is two hash one zero
|
||
|
|
which is one zero base two which is actually two so doing that you get the answer as being decimal
|
||
|
|
if you think about what that is in binary we started off with one zero zero zero we
|
||
|
|
ordered one zero into that so that turns that number into one zero one zero which is decimal
|
||
|
|
ten there isn't a simple way of printing binary numbers in batch unfortunately if you have
|
||
|
|
difficulty visualizing them you can use bc the bc program can display stuff to different
|
||
|
|
bases so I shown an example if you echo the result of if you echo the string ob a s e equals two
|
||
|
|
o base that means the output base the base to use for output in bc for all that with the semi
|
||
|
|
colon dollar b so that echo was a string in double quotes we could put a dollar b inside it
|
||
|
|
pipe that into bc so b remember had been turned into the value decimal ten and then we're asking
|
||
|
|
bc to print out the contents of b which is just substituted into the string using variable
|
||
|
|
substitution so what bc's is c's is ob a equals two semi colon ten sees that in decimal form
|
||
|
|
there was a way of feeding it with with other bases in fact but we're feeding it in decimal and
|
||
|
|
we've asked it to return its results in base two so we see as a response to that one zero one zero
|
||
|
|
so that's um that can be useful if you I used to work in binary quite a lot because I was uh
|
||
|
|
I did a quite a bit of machine code programming in my first job but um I have completely forgotten
|
||
|
|
I can I used to know that one zero one zero was uh was ten but I've just forgotten it just
|
||
|
|
fallen out of my head so if you're having similar difficulties remembering stuff then tricks
|
||
|
|
like this can be useful so I thought I'd include it so that's it for today um I thought I was going
|
||
|
|
to get further with this but if you if you've stuck with me through to the end of this then you
|
||
|
|
can see why I'm leaving it here because there's these these these things are a lot more detailed
|
||
|
|
than you think they're going to be okay that's it then see you next time bye
|
||
|
|
you've been listening to hecka public radio at hecka public radio dot org we are a community podcast
|
||
|
|
network that releases shows every weekday Monday through Friday today's show like all our shows
|
||
|
|
was contributed by an hbr listener like yourself if you ever thought of recording a podcast
|
||
|
|
then click on our contribute link to find out how easy it really is hecka public radio was found
|
||
|
|
by the digital dog pound and the infonomican computer club and it's part of the binary revolution
|
||
|
|
at binrev.com if you have comments on today's show please email the host directly leave a comment
|
||
|
|
on the website or record a follow-up episode yourself unless otherwise status today's show is
|
||
|
|
released on the creative comments attribution share a like three dot org license
|