Initial commit: HPR Knowledge Base MCP Server

- MCP server with stdio transport for local use
- Search episodes, transcripts, hosts, and series
- 4,511 episodes with metadata and transcripts
- Data loader with in-memory JSON storage

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
Lee Hanken
2025-10-26 10:54:13 +00:00
commit 7c8efd2228
4494 changed files with 1705541 additions and 0 deletions

232
hpr_transcripts/hpr1757.txt Normal file
View File

@@ -0,0 +1,232 @@
Episode: 1757
Title: HPR1757: Useful Bash functions
Source: https://hub.hackerpublicradio.org/ccdn.php?filename=/eps/hpr1757/hpr1757.mp3
Transcribed: 2025-10-18 08:53:23
---
This is HPR episode 1,757 entitled Useful Bash Function and in part of the series Bash
Crypting.
It is hosted by Dave Morris and in about 28 minutes long.
The summary is some Bash Function that may be on use in your crypts.
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.
Hi everyone, this is Dave Morris, I'm going to tell you today about some more Bash Things.
I quite enjoy writing Bash Scripts.
I think Bash is quite a good scripting language considering it's a Shell script.
The reason I like it is because compared to some of the scripting languages I've used
in the past of a similar type, it's pretty sophisticated.
I used the CSH Shell at one time and I don't reckon it's anywhere near a sophisticated
as Bash.
Anyway, I've got to write quite a lot of scripts and the moment my little side project is
to write myself something where I can manage the whole process of preparing a show for
HPR and this suite of Bash Scripts is getting quite complicated and along the way I'm writing
quite a lot of functions to do various tasks between the scripts and things.
So I thought it might be useful if I just set off on a journey of describing some of
these functions for the benefits of anybody who's interested, maybe set up a scheme
whereby people write stuff or share stuff that they've written under the heading of Bash
and on HPR.
Anyway, there's a series on Bash on HPR.
So I've got a couple of functions I'm going to talk about today.
They're designed to be used in Shell Scripts.
There are a few others that I have which I use on the command line because you can effectively
build yourself a command by setting up a function in Bash.
I'll leave them for another time.
What I tend to do now is to store the various functions that I need for a particular project
in a file and then I source them in my script and in the notes and the longer show notes
that I've provided, I tell you how I usually put them in something called function under
school lib.sh and then in the main script I look for this file, check that it's there
and if it is then I source it using the source command in Bash.
So that just loads all these functions and means you can share them around like a library.
So the first one of the two I'm going to talk about today is they're both fairly simple
but quite, I like using them anyway, I spend a little bit of time fiddling around with
them to try to get them the way I want them.
First one's called pad and its function is to just simply write bits of text to the screen
in a formatted way.
What I wanted to do is to put out a message with a line either to the left or to the right
or around the message so that it was highlighted on the screen if probably I'm a keen CLI user
so I tend to write bash scripts that do this sort of stuff, talk to them through the CLI.
So the arguments that this script requires are, there are four of them, the first one
is the text that it's to display then the next one is the length that it's to put this out in
and then the third one is the character is going to pad it out with and the last one
is LR or C, the letter LR or C where the default is R which means pad to the left or center
the text.
There's some examples in the show notes that show how, for example, you could use it to
output a title centered in a line of 40 characters so I want to tell you, there's no point in
me reading these when they're in the notes hopefully you can refer to them.
By default if you just put in pad space and then in single quotes a hyphen then it will
output 80, 80 hyphons so it's just a useful way of drawing lines across reports and things.
So I've included the code, it's only 33 lines including comments and I'll just walk you
through an explanation of what it does.
Now I think I've probably said in other talks about scripting that I use VIM as you
I'm sure you know and I use a plugin for Bash which is called Bash Support and it will
generate boilerplate for you so you can get it to plant the template for a function in
the thing that you're developing and as part of that it generates a comment header to the
top of it and the example I've got here shows it shows what it produces just a template
to be filled in.
So the functions pad line 10 you see it being declared then lines 11 to 14 are declarations
of a bunch of local variables.
I like to do this as a way of passing arguments into a function so I like to name all my arguments
with local names.
I use the local specification to make sure that these things are local to the function
don't leak into the calling script.
So I put argument 1 into a variable called text.
What I do is I use the Bash parameter manipulation feature called display error if no or unset.
These have really catchy names which simply checks to see that there is a value when it's
doing the setting of the thing and if there isn't it will abort the script with a message.
So I'm using this to do a sort of usage message so if I happen to call this pad function
wrongly it will generate an error message with the way that scripts often do to say no
this is how you use it.
Length, char and side are the variables that hold the next three arguments and they all
default.
So length defaults to length of 80, char which is the padding character defaults to a
hyphen side which says which side the padding is to go defaults to which means pad it on
the right.
There's some other local declarations that are on line 15 as well.
One of the things that this script, this function needs to cater for, it doesn't cater
for every possible problem but it's relatively easy to use it in a way where you might cause
it to break if you try and give it text which is longer than the long as or longer than
the length that you specify so if you give it a piece of text 40 characters long and you
ask it to pad that to 40 characters that's just silly.
So there's a test on line 17 that says if the length of the text variable is greater
than or equal to the padding length that you've asked for then just simply print the text
and exit the function, exit tidally so it'll just print it, not even bother to pad it
because it makes no sense to do so.
On lines 19 and 20 the other two arguments are processed so the char padding character
argument we only want to cater for one character there so for some reason or other more than
one's been provided just chop the first one off and use that.
These are all using bash parameter manipulation features which I did a talk about which is
referenced in the notes and also the side the LRC thing, you might provide that as a
lowercase character and so line 20 forces it to upcase just to make it easier to test.
The main aspect of this, the meat of this function is line 22, line 22, 23 really.
22 it uses the print F feature to generate the padding characters and the way it does that
it uses the minus V option which puts the result of the print F into a variable so a variable
is called line.
The format spec is percent asterisk s, what that means is put out a string of some length
where the length is provided by one of the arguments of the to follow so the argument
that's provided is a simple calculation which is the length specification defaulting to
18 if you remember minus the length of the text so really the padding length is to be the
amount of pattern, the number of padding characters to be that the remainder after you subtract
the length of the text and then the second argument to print F is a space enclosed in
single quotes so what that will do it will put out an arbitrary number of spaces into the
variable line. Why spaces? Well print F is only about outputting strings and numbers and
things and the only thing you can put out repetitively is a space. So line 23 then takes all
those spaces and converts them to the character that you've asked for to be used for padding it
does that from the one line. So then all that's needed is for the function to decide how it's
to to to produce the final final padded output. If the specification of side was R then it's
to put it on the right if it's L on the left and if it's C is put in the center so R and L are
fairly simple they're dealt with in a compound if statement which says if it's R then put
the text then put the the padding characters on the on the right if it's an L put them on the
left and if it's C then take the padding characters split them in two and put them either side of
the of the text and if you look at lines 30 and 31 you can see 30 computes what half of the
line is and 31 chops off the first half outputs the text and chops off the second half I do it
that way but just in case that it's a it's an odd number so that you get the you're going to get
slightly imbalanced pieces either side so it's fairly simple I mean it does what I need it
it might be a little bit too simplistic you might not like it very much so if you wanted to
pad something with spaces it won't do it because it's using spaces internally to generate the
string and then it converts them to to characters and the way I've designed it doesn't really
cater for that suppose I could change it to make it deal with that I hadn't really thought much
about it until I was writing these notes and I haven't done anything further with it it might be
too simple for your taste but it does does what I need and it's hopefully something of interest
that you might want to develop if you do then come back and tell us what you did that would be
interesting these are as I say basic functions as part of my toolkit I'm using for script development
and the next one I have called yes underscore no and it's simple as a simple thing you use to ask
a question and wait for a reply which is something my scripts are doing fairly often the way I've
constructed it is so that you can use it as if it's a sort of boolean function that you'd use in
a high level language and you'll see that there's an example of an if statement so it's if exclamation
point yes no so if not yes no and then yes no is followed by a prompt string which is the thing
you're going to ask the user this case it says do you want to continue and then there's an
optional default value that follows that which in this example is no so it will actually prompt you
with do you want to continue question mark space and then it will it will offer you the no
as an option so if you just hit return it would it would not continue you can see that it would
return true or false and then it's being negated so if it returns a false then that will be turned
into true and it will exit whatever bit of code it is that you're running this in so it just
returns a numerical answer true which is zero in bash and one which is false the anything non zero
is false I think in in the bash environment so let's have a look at the code of this one this is
another quite short function it's only 35 long 35 lines along including the comment and it does
the similar sort of thing lines 10 and 11 are sorting out the arguments puts the first argument
in a variable called prompt and if there isn't there isn't an argument then it will abort things
with the message the second argument is is a default and that in the in in the the definition
of default it's actually stripping out spaces so the thing where it says dollar open curly brace
two slash slash space slash close curly brace that means strip out all spaces remove
replace all spaces by nothing because we don't want to cater for responses containing spaces we
are only prepared to deal with y for y or yes actually y or y e or y e s as the as the yes returns
to anything else as the null return so it does that there just simplify matters lines 14 of 15
the 14 to 16 I should say are dealing with the the default instance so if there is
a default value provided then the default variable is replaced with itself preceded by a minus i
in a space and I say in the notes that strictly because this this is I'm actually making an option
for a command but further down strictly the after the minus i there should be a quoted string
but since I've made sure that the value of default is never going to contain spaces and you'd
want to quote it if it did contain spaces then I've short circuited things a bit there made it
a bit simpler so line 21 is the main read which gets the puts out the prompt and gets the answer
and it uses a minus e option which invokes read line read read read line library which is what
you will get on the command lines thing that lets you do editing at note all the various control
keys and stuff that let you do line editing and so forth so it'll use that in the read it doesn't
by default so you can't do things like backspace and delete things and add stuff to a line so I
always do this it's then followed by the the value of default default variable now if there was
no default then it will be null so nothing will be be substituted there at the time the read is
but if it if there is a default value it will there will be placed there a minus i and a string
then minus p followed by the prompt which is enclosed in double quotes as you see because it
will pretty much certainly contain spaces that's the prompt that you're going to get when the when
the reader's invoked and the result of whatever's typed in will will be returned in the variable
and an s now line 22 is capturing the result of the read the read will either return a true value
if it worked if it did did its thing correctly or it will if it was aborted for whatever reason
it will return a non-zero now one of the things you might do is press control d control d is
end of file and if you ever do that to a read it it causes the read to abort because it's not
it's it's it's got an end of file indication and I'm catching catching that eventuality in the
script so lines 23 to 26 are looking for a non-zero return from the the read and if that happens
then the message readaborted is put and the script the function I should save returns with a
false value it's fine it's slightly confusing fault is one but you know it's just the way you
have to live with it so that's really just catering for what happens if you do control d otherwise
we pass on to line 28 where the the result that came back is forced to uppercase that just as
before makes it easier to check the results then the line 29 I apply a filter to the to this
returned result where anything that is not the characters in yes and the words yes and no
is removed might be slightly controversial I mentioned a bit more about this later we at that
point will have the answer in the the form which is the easiest to check if statement that begins
at line 30 and ends at line 34 is then checking to see if the answer that was given
matches with the word yes and it does this using the bash regular expression syntax and you see
the equal followed by a tilde that means the the thing on the right is in regular expression the
regular expression is an up arrow which means anchor this to the start of the line we don't
expect there to be anything at the beginning of the line other than the answer and it's got a
dollar at the end which means we don't expect anything else after it before you reach the end of the
line and then we look for a Y optionally followed by an E or an E and an S so catering for a Y
as a response a Y E as a response or a Y ES as a response and only that if we find
any of those conditions any of those items then those characters I should say then we have a
positive result all the question mark in the regular expression case you didn't mention that the
fact the regular expression the E and the ES are in in a bracket in brackets that means that
just encloses them as alternatives and the pipe symbol between the two alternatives is an OR
the question mark means the E and the E and the ES options can be omitted totally so you can
just have a Y that'll that'll be what returns your positive result and anything else anything
doesn't match it at all will return a one which is false so that's it it might be a little bit
controversial doing it this way I came up with this idea thinking oh that's quite cool but having
thought more about it I'm not sure I'm right if you type an example I put in the notes
something silly like yep great as a response that will be stripped right down all the
all the characters other than yes no will be stripped out of there and it will resolve down to Y E
so it'll be the Y from Y and the E from great so that's a match you might also if you type
yeast why the hell you do that I don't know but there you go that also matches because it's got a Y
and an E and the rest will be stripped away depends if you think that that is deeply stupid
that your yes no thing can take stupid answers and make decisions on the basis of there being
something it looks a bit like yes in there then you might want to skip that bit that strips out
the yes no stuff online 29 I might do that later actually I'm not sure the other thing you might
not like in this design is the default the default the way this will work is that in that
that example early on in the notes do you want to continue whether default is no then the answer
will already be provided but if you wanted to say yes you can't just press return obviously because
that will return no you'd have to delete the no the default value and you know there's
there's some potential annoyance there I just hit control w which is the universal
delete back to the start of the line and then press Y and that would that would do it
better than wine return of course so it suits me sometimes so I define it irritating slightly
but you know depends on your your particular tastes I hope you find that useful that's the
end of me talking about these things for today I've given you some links to stuff about
writing functions there's a lot to learn I find the Linux documentation project stuff quite
helpful it needs some careful study but it's it's pretty good and the sources of these two
functions are available in one file that you can download which are also linked okay that's it
thanks a lot 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 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 contributing to find out how easy it really is hecka public radio was
founded by the digital dog pound and the infonomicon 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
under creative comments attribution share a life 3.0 license