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