Files
hpr-knowledge-base/hpr_transcripts/hpr2096.txt

237 lines
19 KiB
Plaintext
Raw Normal View History

Episode: 2096
Title: HPR2096: Useful Bash functions - part 2
Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr2096/hpr2096.mp3
Transcribed: 2025-10-18 14:16:07
---
This is HPR episode 2096 entitled Useful Mash Functions, Part 2 and in part of the series
Mash Crypting.
It is hosted by Dave Morris and in about 23 minutes long, the summer is the further development
of a Mash Function that may be on use in your scripts.
This episode of HPR is brought to you by An Honest Host.com.
Get 15% discount on all shared hosting with the offer code HPR15.
Better web hosting that's honest and fair at An Honest Host.com.
Hello everyone, this is Dave Morris.
Now today I'm going to be talking about Bash and some functions that I think you might
find useful if you're into that type of thing.
Now this is one of those shows where I have put up quite a lot of code and I'm going
to talk about it.
So if you're not interested in this then you can skip ahead.
If you are interested I would strongly advise that you listen to this with the code in
front of you unless you have a very good ability to visualize bits of text in your head
which I'm certainly not such a person so I sympathize if you're not.
So what I'm doing today is picking up from where I left off in 2015, April 28th where
I did show number 1757 which I entitled Useful Bash Functions.
And so I thought I'd come from here and this is called also Useful Bash Functions Part
2.
And what I'm doing this time I looked back at the previous functions that I talked about
and I'd got a bit of feedback from the previous show.
Some of which said the way I had organized things was not really all that useful.
At the time I didn't agree with that but on reflection and on using these functions
because these are things I actually used day and day out.
I got really fed up with the way it was, I thought some of these were working so I've
rewritten them.
I thought I would share one of them with you which was the Yes No Function which was sort
of a bit, I think it was commented on that it was a bit annoying the way it worked.
So as usual if you have anything to say about this, critical or otherwise, anyway saying
constructive critically, critical things is a good thing.
So just please comment or send me an email or something.
So my Yes No, Yes Underscore No Function is a thing which I use in scripts which asks
a question in the form of a prompt and then expects an answer which has got to be a Yes
or a No positive or negative answer when then it will return a true or a false result.
And so what this function actually does is it takes a prompt and it outputs a prompt,
you feed it a prompt and you feed it a default answer which can be Y or N Yes or No.
And it then outputs that prompt and expects an answer or if you don't type anything it'll
go with the just hit return, it will go with the default.
Now the version that I demonstrated in show 1757, the prompt or not that the prompt was
always followed by the default.
So if you provided a default like yes or no or whatever, you would actually see, do
you want to do X Y Z followed by either the word yes or no.
So it actually, it typed it for you effectively which was not ideal because if you wanted
to change the default to something else it offered you no and you wanted it to be yes.
You needed to delete the text and then retype it.
So I've had to go at redesigning this and I've got two versions of it which I want to
talk about in this episode.
I've called them yes, no mark two and mark three.
So I've got an example of using mark two and it consists of if space exclamation mark
which is the not and the negation symbol in bash space yes, underscore no underscore
mk two space open quote do you want to continue question mark space percent S space close
quote space open quote capital N close quote semicolon space then.
So that's an if statement and the thing that follows the the then is return followed
by fi which is the end of the if statement.
So what this is doing is it's firing up yes no it's getting back an answer and if the
answer was true then it will return as the answer was yes it will return a true value
and then it will skip the rest of the if statement and carry on with the rest of the script
because we've negated it we've turned a true result into a false one and if the result
coming back is false it will be negated to become true and then the script will execute
the return statement.
So that's how it works.
So the prompt do you want to continue percent S is what gets put out and the the other
argument is the default.
So when you run it you would get the prompt do you want to continue question mark space
then you'd get square brackets low case Y slash capital N close bracket and that's
been replaced by the function that's replaced the percent S string now this low case Y slash
capital N business is a convention you'll often see in command line tools you probably
have and you're wondering why I'm telling you about it but just in case you haven't the
square brackets hold the two possible responses in this case which there's only two possible
responses and the default one is capitalized.
So this one shows that the responses should be a Y or an N but if nothing is typed
then it's taken as being an N and the case of these things is a relevant case in the
in the square brackets simply denotes which one is default.
So I then launch into the function itself and it's a bit different from the previous
version so I will go through this one but when we come to mark three I'll skip over
a lot of the details because they're similar.
So yes no mark two it starts I've got a numbered listing of it here in the notes in the
full notes starts on line nine preceded by the usual comment and on lines 10 to 12 there
are various variables being defined some of which hold two of which hold the arguments
the variable prompt and default hold the two the two arguments are given to it and also
provide defaults as appropriate in fact prompt is mandatory so that bit of bash parameter
substitution causes the whole script to fail with an error message if no prompt has provided
the default is set from argument two which is forced to uppercase it's just so we don't
have to bother about checking for for different forms of the the answer.
So lines 14 to 28 are all about dealing with the prompt string and as you've seen in
the example you can provide the prompt string with a percent s enclosure which is a substitution
point for this square bracketed business.
So first thing that happens on line 14 is that a bash regular expression is used to check
to see whether the prompt variable contains the string percent s I plan to talk about bash
regular expressions at some point in the in the future so I'll not go into details here
but if it is if there is one of these things in there then the rest of the lines up to 27
are executed if there's no percent s then we don't care we're just going to carry on we
don't need to do anything special to the prompt then on line 15 we have a check to see whether
there is a default value the minus n option inside the double square brackets which is bash's
testing capabilities in an if statement minus n means not blank not empty so if that's if the
default exists if there is a default value then we want to do particular stuff if there's no
default value then there's an error and we abort the whole script that's on lines 25 and 26
where an echo is produced which puts out an error message that says default required so if
you're going to use percent s you've got to provide a default or as it makes no sense and we
use on line 26 we use exit which not only exits from the function it also exits the script
that's calling it because whoever's written the the script is obviously messed up so we just want
to abort at that point so lines 16 to 23 now so what happens if there is a default and lines 16
we set default to the first character of that particular string because it might be a multi
multi character thing might be NO or YES or something then depending on what we get back there's
a case statement which begins on line 17 which is which uses default as the default variable as
the switch variable and if default contains Y then we construct reconstruct the prompt string
by using it as the format string to to a print f and adding square bracket what a capital Y
slash lowercase n closed square bracket as the percent s and we put that back into the prompt
variable so that's the line that says Y closed parenthesis print f space minus v space prompt space
open double quotes dollar prompt closed double quotes space double quotes square brackets
uppercase Y slash lowercase n closed square brackets closed double quotes and then two semi-colonzes
the way you end one of the branches in a case statement in bash so if the prompt was if the default
I should say was Y began with the Y then we want to put in the appropriate element in the
in the prompt string that shows that the default is for the end branch then we do the equivalent
thing but with the case the other way around so that the default is obviously a NO and in if we
get neither a Y nor an N which is the the star instance the star case in the case statement
that means anything else then we do another one of these echoes with an error message saying
the default must be Y or N and exit the whole script and the next line is a double semi-colon meaning
that's the end of that branch esac on line 23 is the end of the case statement I wanted to mention
how this echo error message is constructed the the echo string is in double quotes so you can put
parameters in it you can put parameters of substitutions in it and what we do is we substitute
dollar open curly bracket funk name f u n c n a m e all in capitals square bracket open square
bracket zero closed square bracket close curly bracket that means the array called funk name
the zero element now this is something that's maintained by bash and it keeps the name
of the current function that you're in on the it's it's sort of a stack similarly a bit further
on in that line we have a line number so it's line space and then the substitution point so
we're using dollar open curly bracket bash underscore line no which is all in uppercase in the
square bracket zero or close square bracket and this is the current line number that we're on
in the bash script so it's it's just I just put that in because I'd in the intervening
intervening time worked out how to do that and thought it's a useful thing to put in error messages
because you get more information about where things failed if you're developing a script so
after we've been all through all this stuff between lines 14 and 28 we've come out if we have
come out because we haven't bought it due to errors we've come out with a prompt string which
has been rewritten to contain this square bracket y slash n business so line 33 through 38 they're
pretty much similar to the original but I'll just read them quickly because you probably
have completely forgotten about how it was done originally so we've got a read statement read
space minus lowercase e space minus lowercase p and then the followed by space double quotes dollar
prompt close double quotes space a ns and so what that's doing is it's outputting a the prompt
and receiving back an answer which is storing in the appropriately named variable a ns then line 34
has got res equals in double quotes dollar question mark this is the result returned by the read
statement so if anything went wrong then we want we can catch it there and deal with it so this
is followed line line 35 to 38 by an if which says if dollar res is not equal to zero it should come
back as equal to zero meaning everything worked okay then echo re-deborted return one so the most
common thing that will happen is if if the person using the script can types control d which is
the sequence that you use to say that's the end of what I want to type and so then it's an end
file marker and you can use it to abort read prompts if you do that then the script will this function
will return a re-deborted message and will return one the value one is false so should have
returned the default perhaps I don't know anyways the trouble with reading these things as I think
about them I'm I'm thinking of other ways I could rewrite it anyway we leave it as it is for
moment and line 40 we're looking to check see whether an answer was actually returned whether whether
the the user just pressed return in which case the and variable will be of zero length and that's
what that test is doing it's using it's not using an if it's using one of these shortcut types of
bash expressions so in square brackets we have minus z space double quotes dollar a n s double
quotes and then ampersand ampersand space a n s equals open double quotes dollar default double
quotes so we're checking to see if if the and variable is empty and if it is and we put the
default in there then lines 41 to 45 are actually actioning the returned result so the if statement
checks to see whether the variable a n s which we force to uppercase is matches the regular
expression the regular expression consists of circumflex capital Y open parenthesis capital E
vertical bar capital E capital S close parenthesis question mark dollar now this is a regular
expression which looks for Y as the starting character and then that can be optionally followed by
an E or an ES and that's why they're in a parenthesis group with an alternate alternation vertical
bar in the middle if you've listened to my said series you should recognize this except
that in said you have to put backslashes in front of a lot of things the question mark after the
closing parenthesis means you don't have to have the things after the Y so just to plane Y or a Y
E or a YES or match and the dollar at the end simply says that's all you expect and you expect
the end of the line at that point so if that matches the script returns 0 which is true otherwise
it returns 1 which is false and that's it it's actually fairly simple except that there are some
slightly tricky things along the way if you're not up to speed with bash perhaps now there is a
problem with probably several problems with the mark 2 version and the thing that struck me as I
was developing this was that if you type Y you get the answer it treats it as if you're saying yes
but if you typed X or anything that is not an N including an N itself is regarded as no so that's
that's a bit messy if you accidentally if you went for the Y key and missed then it would be
interpreted as N and it could be something quite important that was being asked for confirmation
so I thought I would develop a mark 3 version to make like this a little bit more resilient and
it's essentially the same again it's listed in the long show notes it's pretty much the same
all the way through lines 1 to 32 everything is that it's pretty much the same the difference is
that online 33 we have a wild loop so there's a loop in this which will keep on checking what
is actually returned in the way of an answer the wild loop consists of the word wild space then true
semicolon space do I like to write my wild loops all on one line you can split it after the true
if you want to so the semicolon put the do on the next line so what's true well true is actually
a built-in feature it's a built-in bash command which just returns a true value true being zero
so while true do and the loop ends on line 57 means keep doing this loop forever there's no
condition there that will ever stop it so lines 37 to 42 are the same read and check and give up
on to control D thing that we saw in the earlier version of this in the mark 2 version line 44
is the same as before where it's checking to see if ANS contains anything and if it doesn't
setting it to a default then the real the real change the main change apart from the wild loop
is line 50 through to 56 where we check the uppercase version of ANS on line 50 against that same
regular expression that will match a Y or a Y E or a Y ES and then it will return true you know
that matches but then line 52 we're doing a further test that if it wasn't that then is it equal
to know where the the regular expression is circumflex capital N capital O question mark dollar
what that means is start at the beginning of the line look for an N followed by an O but the
O is optional because it's followed by that question mark and then we want the end of the line so
N O no way or something like that being typed in would not match if that matches we return
one which is false and if neither of those match line 54 the else branch we output the message
invalid reply please use Y or N and line 56 is the end of that compound if so what we have here
then is a thing that takes in an answer checks if it's yes or no and stops the loop annex it's the
function with a value but if neither of those are returned then it will produce an error message
and the loop will go around again so that the the functional keep on and on and on asking the same
prompt until it gets a valid answer so I've given a typical use in the notes which is which is
pretty much the same as the example for the mark 2 version so if I won't read that letter by
letter but if not yes no mark 3 then in quotes do you want to continue percent S close quote
the default is in quotes and it's a capital N semicolon then then we echo finished and we return
at that point so if you ran that ticket if statement in a script or from the command line if you
wanted to or it never do that myself personally but you you might get the following dialogue which
I've shown in the thing in the in the notes do you want to continue and you've got a lowercase Y
capital N so the default is no and who the the response here has been what it comes back saying
invalid reply please use Y or N do you want to continue in the same question type YO the previous
the previous version not the previous version the original version would have accepted that YO
as a valid as a meaning yes but in this case it says no valid reply and then the next answer is
NOPE NOPE well that also doesn't match because there's a P in an E after the NO invalid reply it says
and then asks the prompt again and finally this rather awkward person types NO which point
the script says finished and awards and stops exits so personally I say that the mark 3 version is
more useful overall and the one I'm I have adopted myself in a number of places and it's it's
just it's not perfect there's still things you could do to it actually some of which I thought
of as I was reading this stuff but yeah it's it's a bit better if you have for any input if you
have any suggestions as to how to make it better then please let me know there's a version of it
which can be downloaded which is linked in the notes so if you want to grab it and use it in
your script or mess around with it or improve it or whatever then please feel free and if you do
improve it as I said let me know that would be great okay we'll call it quick stay hope you
enjoyed that bye now
you've been listening to Hacker Public Radio at Hacker 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 and click on our contributing to find out how easy it really is Hacker Public Radio was
founded 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
show is released on the creative comments attribution share a light 3.0 license