 Well, it's that time of the week again. It's time for chitchat across the pond. This is episode number 768 for May 27th 2023 And I'm your host Allison Sheridan this week our guest is barbou shots with programming by stealth installment 151 not quite the ring of 150, but we're marching on Well, you could argue with 152 age What's 152 is that something well now it's a rounder number Okay, you're just being silly now. What are we gonna do this week, Bart? We are going to have a slight change of plan because our listeners rock So we we we had I think an excellent episode last time all about redirecting the various posic streams I'm really happy we redid it. Um, oh, yeah And I got a lovely message from listener Jill of Kent who is very Insistently of Kent to be added since there are now two amazing listener Jill's and so we need to be sure we credit the right listener Jill That's right, right? so we talked about the fact that Slash dev slash gty represents the terminal and we also said Unfortunately correctly that you can't tell if there is or isn't something waiting for you in standard in in a cross-platform way You can do it in bash 5 which means it won't work on the mic But you can't do it cross-platform and that remains true, unfortunately, but Jill did have a fantastic little tip so If you remember back to when we did when we first met conditionals We learned about the square bracket square bracket built-in function for doing for evaluating a boolean And I mentioned that you know, they were commonly used operators like minus F or is it a file and minus e for does it exist and minus I think it's D for is it a directory And I said there's loads more, but you don't need the other ones. We'll just take to the more important ones There's one which has just become interesting Minus T can tell you whether or not a stream is the terminal Are we gonna learn about that this week? We are I'm so getting it almost every day when I hear yeah That was me turning Bart back to the order of the show notes Yes, so then we are going to do the first half of what I had actually promised to do today, which is printf and Printf is a fantastic life scale I'm gonna make the argument that printf is a life scale a bit like regular expressions So Pearl gave the world regular expressions. You know how to write regular expressions You don't know how to write a line of Pearl What kind of you do because the regular expression syntax, you know is from Pearl Well to see programming language gifted the world a very common way of representing format strings and Bash just took them wholesale. So yeah, okay, why reinvent the wheel? We'll just take printf from C PHP stole it from C Java stole it from C lots and lots of languages stole it from C So once you learn printf here for us in bash, you now have a life skill that will actually you'll notice it cropping up all over the place Now that once you recognize us and we're gonna know that's a fun with that But of course we have some homework to do before we do anything else So I guess that's where we should get kicked in so we have been playing around with a little script to Read a menu initially it was from a text file present you with a list of options ask you to enter your order and then tell you what you ordered and when last we left our Left our little script I had asked you to update it so that it would default to reading the menu from a file named menu dot txt in the same folder as the script But if you wanted to use a different file You could use the minus M optional parameter to specify a file name Or if you would like to read from standard in then you could use minus M space minus to say actually I'd like you to read the menu from standard in And then I did say that we had added a minus S for a snark flag last time And I told you if you want to make your code a bit smaller you can lose the snark and you said no So you're fine. There's snark stage mine went away because I wanted to have my sample solution Basically, I wanted the important things for this week to not be cluttered So I felt it was better for clarity that I remove it even if you didn't and then the other thing was let me hold you for One quick second here. No, you did say that I misinterpreted something. Okay. I now understand the assignment better All right. Okay, and then the last thing I said was to make sure that no matter which way the pipes are flowing I always wanted the interaction with the user to be through the terminal So whether or not there's a menu being piped into standard in when it comes to asking the user for their order They should always be asked from the terminal from the keyboard not from standard in which would be what happened by default so you had a little bit of work to do to Read and write to the terminal explicitly, which is the last thing we learned in the previous installment Are so basically You will find the full solution as always in the summons of PBS 150 dash challenge solution that sh I am so boring in my naming convention, but hey, I'll collect no that's turned out to be very handy because Ed Howland is organizing your solutions Into the PBS student challenges so we all have our own little folders in our Organization for PBS and we created one for you and he's populating it and he's depending on you to keep consistent with that naming convention It's a good thing. I'm a very boring person Stay boring. No, no, you're consistent and and reliable and repeatable. That is not boring That is what you really want fair enough. Okay. I will keep doing it now. That's good to know and So I'm gonna draw your attention to a few things, but the full solution is sitting in the zip file So the first thing I want to draw your attention to is the use of slash dev slash tty, which is the Special file that represents the terminal and so whenever we need to send a message that will always go to the terminal Like please enter your order. We need to redirect standard out to slash dev slash tty So that way no matter whether or not the order is being piped into a file or piped over to Wc-l to count the lines or no matter what you're doing with the plumbing You always want to ask the user in the terminal what you want to eat Therefore we need to print all of those messages to the terminal therefore we hope we use the greater-than-sign slash dev slash tty after the echo statements to Make sure we're printing to the terminal So I'm gonna stop you because I think it's possible. I will never understand this I know I've been through PBS 150 an entire twice And I looked at the homework, but I didn't come close to figuring out what I was supposed to do with slash dev slash tty I'm confused because we always saw the menu from in the terminal and we always saw the output in the terminal Because it was going to standard error Right, so if you just said we have to put echo to greater than slash dev slash tty to be able to see it Well to be able to always see it Because if you redirect standard error to dev null then all of a sudden your menu goes away So how would it get sent to dev null? How would it standard? The person calling your script is free to redirect anything to standard in and They're free to redirect standard out for standard error anywhere and you have no control as a script author, right? That is how your script is used that happens at use time So do you want your script to always behave no matter how it's being used is the question? Yeah, I guess this is where our silly example Makes Me not even think of that as an option like why would anybody ask for a menu and not want to be able to see it Why would they ever do that? That would have never occurred to me, but this is this is just a silly example, right? Yeah, I'm trying to make the line so that it's silly and fun No, no, it's that's good. That's good though But but that that's opening me up to someone might tell it So it I don't think in your examples actually do you go through and say to send it to dev null and prove that it still comes out? I don't do dev null to prove it still comes out But I do actually in the example pipe the actual output of what you ordered to a text file to prove that we actually have what we Want which is the interaction is through the keys through the terminal and the only thing that ends up in the transcript file is Your order So the conversation with you about your order doesn't go to standard out But what you ordered does go to standard out so it can be redirected Therefore the script behaves very very friendly with pipes Okay, maybe we should keep going through this and I'll and I'll understand that when you get there Okay, so we took the echoes and we we Greater than cymbal them into dev dev slash dev slash dty Yes, to make sure that no matter what the echo statements would always be printed to the to the screen Yes, which is the echo statement to say please choose your order and the echo statement to say you have just are added Whatever to your order so the the two echo statements relating to taking your order The other thing we have to do is make sure that the select statement is interacting with the terminal Because the select statement by default will read your answers from standard in which could be a menu Which would confuse the ever, you know, which would really make a mess if it tried to use your menu as its options All right, if you said minus m space minus then standard in has just been used as the menu So how can it be used now to take option one option to option three you can't okay So we need to make sure that the select statement always reads from the terminal So that means we need to redirect the terminal into the select Which means that after the done we have a less than sign dev tty the done in the done in the select You're talking about the done that ends the select. So the end of the select is the done keyword So when I say at the end of the select that is that is where it goes. It's a little confusing, but hey, that's bash That was the rules Well, that's where we were shoving a file in before it is so correct. Actually. Yes now We're just doing dev slash tty. Okay, and that doesn't keep us from shoving in menu dot txt No, because that's gonna be sitting down it in Which we're going to have used elsewhere that I'm going to talk to you about in a moment Okay, okay So we're saying that no matter what happens when the select menu comes up saying what would you like to eat your answer? Is always coming from the keyboard Doesn't matter. What else has been done? Okay? You're guaranteeing it and we also need to guarantee that when it asks us, you know when it shows us the list of options It should be showing those to the terminal Always so the select statement also has to be told you always talk to the terminal So after the done we also have a greater than slash dev slash tty So after the don't we have two redirections because we need standard in and standard out To be plumbed to the terminal for the select statement Gotcha, and that then works. So that is that is a first piece of important change And then the next thing is how do we load the menu? So in the past we just sort of read the menu from the file and that was that was a very straightforward We always just read it from the file, but now we actually have a little bit of logic to apply and so I decided that the easiest way to apply logic was to Default so to set a variable at the top of my script to default it to Taking the menu from the txt file So I have menu source becomes equal to dirt, you know dollar dirt name bash source Slash menu dot txt which is the file menu dot txt in the same folder as the script So we learned about that so that was the thing that we used to shove in but now you're putting it into a variable So you can use it. Yeah, so it's a variable that now has a default value of well You know what I basically said was if they don't tell me anything else I'm going to assume this so let's actually just make that assumption into a variable assignment and then Okay, we then later on down the script need to actually slurp in I Probably should have included in the little snippets also so in my in my get-opt I obviously added an M for the minus M option argument and whatever you pass to minus M gets stored into menu source So in other words menu source defaults to menu dot txt But if you pass a minus M then whatever you pass is now in menu source So then when it comes to reading the menu I Can basically say well my menu string. I'm going to default it to an empty string So menu string becomes equal to single quote single quote And then I say if my menu source is equal to the minus symbol Then we want to serve standard in which we can do with just dollar cat Otherwise I want to read from whatever file is in menu source it'll either be my menu dot txt default Or whatever was passed with the minus M. So then I say menu string becomes equal to dollar cat menu. So I thought that It was Minus that it was minus M and then minus as two separate things We were supposed to do and so I didn't catch that part of the assignment went back and double checked And yes, you were very clear in your instructions that that's what you said to do But I don't understand how the minus M and the minus still go together. I still don't get it abstract it back So if I add a parameter named L and I expect you to pass me a length then there are two arguments minus L and then four or minus L and then 22, right? It's minus name of parameter value So minus M space value and the value can either be minus or the value can be a file name But it's okay. So if the if the value is a file name I Understand what it does and you're saying if it's if it's minus then it's gonna cat whatever Text string and shoved in metha front, which is standard in yes, okay So I tested your code by just saying, you know dots last the the the shell Script name space minus and it goes out and it gets the it gets the menu dot txt file correct because you passed it and and An unnamed argument Which the script completely ignores so dollar one Oh, okay value minus and my script because it only knows what minus is if it was preceded by the the Optional argument minus M Okay, okay The fact that it ignored it made me think it was doing something different than what it was doing Yeah, so it's just it is just dollar one if it doesn't have we didn't name it it's just dollar one Okay, okay, I think I've caught up Okay, so where was I we've done that bit. Okay, and we've done that bit So then once we have our menu in a string Then we can loop through it as if it was coming from a file So the triple arrow is our here string, which is how we read a string into standard in So triple a lot of the burr triple a lot triple arrow triple a lot with some sort of very soft flower um Triple arrow dollar menu string will read the value of that variable as standard in so we can use that in our while loop to Just process our menu. It doesn't really matter where it came from now because we've shoved it into the very yeah Yeah, yeah That part I understood and that that saved me duplicating my code because I don't like duplicating code that makes me cranky It is a bad smell So at this stage we can verify that the code does what I think so you will find in the zip file an Extra file called menu dash Monty Python dot txt which offers a shockingly interesting menu Can it contains one item on one item only spam? And I suppose you could have made ten items and they're all spam spam I could if I could have had spam egg bacon and spam There you go. I did I did try to be clever with mine even though I stole mostly copied off your paper I made mine called Twitter dot txt and all it had in it was a poop emoji For anyone who doesn't know that's what Apple or what not Apple That's what Twitter PR responds with if you write to it is a poop emoji So then I got excited and I made a fail whale and then I made a rocket with an explosion thing At least I had three to test with Oh, that's great fun. And of course you can even use emoji anywhere because they're just utf-8. It's great Yeah, I thought you'd be excited that I use some emoji. I do like that. I totally copied off your paper Hey, it's all about learning. You can learn off someone else in the class. That's fine So we can call a script with minus m space menu dash Monty Python dot txt and it will let us choose our spam Or we can echo bacon new line eggs new line toast Pipe that into our script and then call our script with minus m minus and then redirect to order dot txt And that proves the whole thing in out because now what happens is Standard in is now bacon eggs toast Which we're going to read as the menu and Yet even though standard in is used when it comes up to ask you what you'd like to eat You're still getting the menu options like you should When you're typing stuff in and it's still interacting with you perfectly and then when you're finished It doesn't tell you your order because that's been redirected to order dot txt But if you have a look in order dot txt it contains only what you ordered and not the chitchat or you had to make your order I Have a very important question on this one. Oh when I ran this command it showed me Four options not just bacon eggs and toast one of the options was done. Where did done come from? Okay, so if you look at the where's the loop and wherever the select loop is Where is the select loop so the select loop? I do I have items in done Yes, as in there is an option that Go ahead. Yeah, so the select loop takes, you know, whatever in and then a list of things So my first thing in the list is just done Followed by the explosion of my array So that means that as far as the select statement is concerned it has done and then whatever the array exploded into ah Good, okay, you're you're working down my list of questions. You've got three down. Oh I'm not even halfway. Go me Okay, so that is the sample solution. I hope that works. Well, no, I know what works. I hope it makes sense So now now I get to go to saying those things a bit you love Kent So What we had left off is that we unfortunately can't tell whether or not there is something in In any particular stream actually waiting for us to read it so we can't avoid blocking Yeah, we talked about this last time. Let's not really rehash that We can detect whether or not any stream is the terminal and this is something that's perplexed me for a while Because there's a whole bunch of terminal commands that appear to do magic and then whenever something appears to do magic I know it's not magic. It's something Bart doesn't know Well Bart now does know how this is done so You may have noticed that The git commands are an example of this the git command if you say git log It will list every single git commit in a repo. So for PBS the git log is quite long We have done a lot of commits and if you do it on the terminal It will pass it through less and it will stop you after every page and make few to hit the space bar But if you take that same thing and pipe it to a file All of it just goes into the file There was no one hitting a space bar there So it knew if I'm talking to the terminal, I will do one behavior But if I'm not talking to the terminal, I will do a different behavior Okay So how does it know whether or not it's talking to the terminal? How did it know? Whether or not it was being piped And the answer is because of this minus t test for inside our square bracket square bracket operator So if you say minus do it, we didn't type a minus t. We didn't type any square brackets Okay, if we want our script to be able to work In the same intelligent way as the git commands then in our script we can detect Whether or not something is the terminal Okay, okay By writing an if statement to say basically if We detect that we that that something is the terminal do one thing else do another thing That is how is doing it Okay So the minus t operator takes just one argument on its right, which is a number Which is the identifier of the file handle So zero for standard in one for standard out and two for standard error So if you say if square bracket square bracket minus t zero Then you know that you whatever code for if t if standard is the terminal else Whatever code for when standard in is not a terminal So I have a wonderfully exciting script called pbs 151 a dash terminal tester that sh Which just has three of statements if minus t zero then echo standard in is a terminal Else echo standard in is not a terminal and in both cases I am explicitly doing my echoes the slash dev slash tty because I know I'm about to start messing around with my streams So I want the script to always tell the terminal what's going on because otherwise if I'm doing redirections I'll lose my output So okay I have another one putting greater than slash dev slash tty on the end of every echo statement Well, no because then anything you do that to can't be piped into a file So we're only doing that when you want to be absolutely certain it's going to a terminal If you do that all the time people are going to be really cranky at you because then your script can't be safe to The output of your script can't be safe to a file. Okay. Okay. All right Uh, so I the same if statement basically three times for t for minus t zero minus t one or minus t two With standard in standard out and standard error So if you try that at the terminal if you just run the script with without any Piping it will tell you that all three of them are the terminal Which is the default right standard in is the terminal standard out is the terminal standard error is the terminal If you did that by just just running the script with no arguments Yes, and in particular no redirections is what matters here because the script the script ignores arguments But the important thing is there are no there's no there's no terminal plumbing. It's we're just running the script If we do a bit of terminal plumbing, so if we say echo pancakes pipe and then send that to our script now standard in Contains pancakes. It's not connected to the terminal. It's connected to the other side of the pipe So now when we run it we will see that it says that standard in is not the terminal Okay, even though we just finished typing echo space Quote pancakes unquote with the terminal it's saying it's not coming from the terminal Correct because standard in is not connected to your keyboard if you read from standard in you were going to read pancakes You're going to read the output of the echo command. Remember the pipe symbol just typed it was my my I've typed it in the terminal with the keyboard That's how it got there. How is that how it got there? That's not where it is So remember the pipe connects two commands together So the echo command we typed. Okay, and the echo commands outputted pancakes. Yeah Okay to standard in got you okay to standard out it outputted standard out And then the pipe symbol took standard came standard in I mean to the to the script Yes, exactly. I'm plumbed at the standard in on the script So the script is seeing standard in as being the output of a pipe which contains pancakes Which is going to ignore, but it's just going to tell us no that's not a terminal I'm plumbed into something Okay If we redirect standard out to dev null by saying name or script forward slash slash dev slash null It will tell us that standard out has now been redirected If we redirect standard error, it's not a terminal It is not a terminal because it is dev null Okay, if we do two greater than sign dev null then we're redirecting standard error to dev null It will then tell us that dev that standard error is not a terminal Or we can go for the full whack and we can echo pancakes pipe it into the script Arrow dev null and then sent to arrow ampersand one. So arrow dev null says take standard out and make it be dev null And then the two greater than number two greater than ampersand one says take take standard error and make it standard out Standard out is already dev null So what we're saying there is make standard error be dev null as well So now nothing is the terminal Okay Now I get why it was useful to have get log Go to less so we could hit the spacebar and the man pages do the same thing But why What are the what are the use cases that you see for this that you wish you had known before? I have to Automatic paging is probably the most common use case You will see that used in a whole bunch of the standard red In fact the system d commands that red hat uses for managing stuff Another place that's used by geese as well as by a lot of modern commands is You can make the terminal do pretty colors by adding in really weird escape characters And you don't want those escape characters ending up In your output if you pipe it somewhere like you really don't want square brackets squiggly whatever ending up They're really horrible escape characters So when you see a command like gate which uses colors to show you what what is what's new and stuff If you pipe that git command to a file the color is gone Again, it's detecting whether or not it's on a terminal and it's only giving you color If it's on a terminal if it's not on a terminal it doesn't fill your output with glop So how would we use any of these? Minus d0 minus d1 minus d2 for the three different Standards, how would we use it to make it go to less? Well, so you could say if not obviously you want to invert so So you might have a variable that contains your output call a dollar my stuff So you'd say if minus t1 Standard out if standard out is a terminal A terminal we say Less space Sorry, we take echo whatever pipe less So echo dollar the output pipe less else echo dollar the output fee Okay, how would it be going somewhere other than the terminal? We would have had to have code that was saying to do something else with it Not code. No. No. Remember. It's about how the script is used So if you write this script and someone puts a greater than sign my output txt Then your script will respond By having a different branch of that if statement Got you good. Okay. Okay So it's about how that's fine used. Yes. So your script is detecting at runtime What's what's what's around me? You know your script is aware of its surroundings Or you can make your script behave differently depending on how it was called All right. Very fun. It is very fun. Thank you. Jill of Kent. I was very pleased. Very pleased. Okay. So now we're going to move into conceptually less confusing territory We are going to make our string outputs nicer At the moment when I have Output at a variable as part of our output We've just said echo and then we've used an interpolated quote So a double quote and then we just put the name of the variable in so, you know In there with the dollar sign in front of it And it's taken whatever was there and just Splattered it into the middle of the string and I put in it Which is fine a lot of the time But maybe we want a teensy-weensy bit more control Like maybe we want to always round it up to having two decimal places Or maybe we want to always pad out a string so that they line up nicely Or there's all sorts of things you want to do to format output more than just splat the variable Completely unchanged straight into the output, which is all we can do with echo And that is why print f which stands for print formatted That's why that c function was written And c the c language was basically written to write unix So it's probably not a surprise that the shell scripts inherited from c given That you know c lives in that's where c sorry the bash lives in the same place, right? It's a unique c thing and like I said before Print f has made its way all over the place. It's become one of those de facto standards If I want to do string formatting we'll do it that way. No objective c has it Do you remember there was a nasty bug with apple's routers that if you named your a wi-fi network Something with a percentage sign in it your network. Oh, yeah, that was yeah, yeah Because the special character to say this is something special in a print f is percent Oh So you you will recognize it really did leak in somewhere. Yeah, it really did leak in somewhere so The print f command is kind of fun. It's really really easy to just get going with it But it's really really powerful So it will probably take you the entirety of the rest of your life to learn everything But it's fine because no one person needs everything So you can learn what you need 90 percent of the time really quickly And if you need to learn something else you can do a quick google And you'll very quickly find the format string to do the weirdo thing you needed to do and you can pop it in So we're just gonna do a spoiler here. I have read ahead and I think this is really fun I I imagine you're going to have way too much fun with the the bits where you're formatting tables I can just see you having way too much fun with that Um, yep, I was already experimenting Good good good. That is what I want um, so We're going to focus on just the bits. I think are important And if you ever need more know that there is more And then you know at this stage we're 150 something episodes in so at this stage I'm hoping people are are comfortable ending up on stack overflow and having a read Or yeah, open the documentation and having a read so The basic structure for the print f command is print f The first argument is the format string So this is what is a format string? Because you don't define that in the show notes. That was question number four. You never say what a format string is Okay, I guess I need to re I guess I need to rephrase my show notes. I do actually have a title print f format strings as a h2 but I guess I guess that isn't clear enough. No, it says better string formatting with print f Yeah, that's the h1 I even checked with Dorothy to see if you had already told me this so that you wouldn't say Allison, I already told you what a format string was so tell us Bart. What is a format string? Well, I'm actually going to put you on pause on that. I promise you it's coming one page down in the scroll bar um So you can't use the phrase until you get to that then Well, no, I need to tell you what the arguments are. I need to here is the lance, right? This is this is a country. It has a couple of cities. We'll look at each city in a moment So the print f command the first argument is this very important format string Which is going to take up most of our time today And then after that are zero or more additional arguments and so The format string contains placeholders And the additional arguments are the values that are going to get shoved Into those placeholders So if your format string contains four placeholders You need to have four more arguments to give you the four values for your placeholders Okay, it's funny that they Define those new that new terminology. That's annoying that because you could have called them variables But they're not called variables. Well, they're valid that they're If it's something that has a symbol and you've got a value you're going to shove into it That's a variable. It's just another name for it. But I don't know why they didn't but it's inside a string So if you use the word variable people get really confused because it's inside a string so You put variables inside strings all the time with dollar parentheses the variable but that's a bash thing This is not a bash thing as far as bash is concerned a format string is just an ordinary string that contains the percentage sign It's only the print f function That takes that ordinary bash string And the print f function is doing the magic So from bash's point of view, they are absolutely not variables. They are just the percentage sign and another character Okay, it's a subtlety, right? But the print f function is where the magic happens So the print f function takes as its first argument a string And then whatever amount of extra arguments you need to fill up All the placeholders in that string And that will depend entirely on what you're trying to achieve. So the number of arguments will vary over time By default print f writes to standard out So you can use it in place of echo. You can just substitute in print f instead of echoes But what if you actually want to take three or four pieces of information? Format them nicely But save it to a variable. I mean that is not an unreasonable thing to want to do So print f does support that with a named optional argument v for variable, I guess So you can say print f space minus v space name a variable Then your format string and then whatever values you want to shove into that format string And then instead of the output going to standard out it goes into the variable Okay So we can as I said those examples in the show So the first example is a very basic print f So print f the first argument is the string i space like space to space have percent s space percent d space times a week exclamation point new line character And then we pass a second argument of pancakes and the third argument of five And when you run that it says I like to have pancakes five times a week Because the percent s is our first placeholder and that becomes pancakes And the percent d is our second placeholder which becomes five and again we'll look at why they're s and d in a moment, but The basic structure is print f string value value So far so good Yeah, I want you to tell me what a format string is pretty soon Yeah, using two lines of it now two lines that that apparently was a format string that you just read to us correct. It was yes. Yes and I hear that we have another example Serving into a variable dessert and then we can echo our variable dessert and you can see that and instead of Going to the screen our four-minute string was saved into its variable So yeah reading this it makes perfect sense. It's really simple syntax Definitely simple is the phrase i'm going to use yeah So oh because it's a single digit Yeah, and a single string or we're not doing any we're not doing any We're not doing anything clever with it, right? We're just taking a simple value and shoving it out so The format string that first argument that is where The power and the complexity are are hiding in plain size So really for the rest of this installment, we are going to talk about those format strings, right? so at first What's a format string burt Is the word is the quote I like to have percent s percent d times a week Unquote is that the format string? Yes, the first argument is the format string so A format string is what it is a string that contains these things. I'm not allowed to call variables place percent s and percent d placeholders Yes, okay, so any string that has those placeholders in it that are that come after a print f That's what a format string is Yes okay Yeah, so print f will will treat whatever you give it as its first argument as the thing I'm supposed to transform so print f okay, so it's What was confusing me is I thought it maybe the percent s was the format string That's why I've been trying to get you to tell us what it is because I I didn't know which it was It's the whole string that happens to contain those placeholders Yes, so the first argument the whole first argument is the format string Uh, no, it's not the first argument because you've got print f minus v dessert Okay, so the minus is an optional argument which gets stripped away by opt out by by by by Opt args arg ops. Ah get ups. Opt arg get ups Right, so the first so even there that when the minus v dessert is processed the first actual argument is still the string All right our optional argument is the minus v dessert so the first real argument is still the format string Even in both examples the first argument is the format string Hmm Okay, you can have an optional argument that is not the first argument Which is how if I say to you that the first argument of ls is the folder you want to list if you say ls minus l You don't then say to me well no bart the first argument is now minus l If I say ls space minus l tilde, you're not going to argue with me that tilde isn't the first argument I would have until you've just apparently it's not optional arguments are not considered you're saying because it's not dollar zero Yes, exactly precisely. Okay. Okay. Okay That makes sense okay, so Everything really from now on is about that string, right? It's all about that string and in that string It so that string is made up of three things, right? So Inside that string there are three possible things that can exist There can be escape sequences There can be format specifications, which is a terrible name. I didn't make up Fortunately, I'm reading from the manual Good because I would have yelled at you because it doesn't make any sense It doesn't make any sense But okay, I went I checked the manual to make sure I was using the right words And I was using way censor blur words and the manual told me nope. They are format specifications I abbreviate escape sequences escape sequences format specifications and then what's the third thing plain text if you're not one of those two you're just text and what the what printf does with just text is it just printed So unless you're an escape sequence or a format spec You're just going clean through. You're just getting whatever you are in. That's what you are out So you just get past it So let's start with the escape sequences because they're easy They start with a backslash And then as far as we're concerned, there's only really three of them that matter to us and there There's there's two of them that matter to us and there's a third one. We need to be aware of So backslash nf is for a new line back says t is for a tab They are the two most important ones And should you need to have A backslash in the actual output Then you have to do backslash backslash Okay, because otherwise it doesn't work So I have a very very silly example Which shows that bash is actually quite clever in its printf So if you're only using slash t and slash n you can use an interpolated or an uninterpreted String so single or double quotes and it will work fine So if you printf ho slash t ho slash n ho slash t home slash n Or if you do the same thing in double quotes, it will print out Ho tab ho new line ho tab home And it would be properly lined up And it will do it correct which makes a lot more sense if you're looking at the text I bet nobody could hear that but I know what you mean because I'm looking at it So it works fine whether you've doubled or single quotes, which is a relief Because within a double quote slash n actually does have a meaning as though slash t But basically the printf is like well, you've given me a literal tab I'll interpret that the same as a backslash t and I'm happy Oh, you give me a literal new line character. I'm happy with that So it's fine what slash t and slash n in either type of string That cannot be said about backslash backslash If you want a backslash in a single quoted string It's just backslash backslash If you want a backslash in a double quoted string The double quotes are going to interpret everything once so backslash backslash gets collapsed a backslash So if you want what gets as far as printf to be two backslashes you need four of them to start with This is never going to need a backslash. I'm never I'm going to make sure no matter what happens I'm never going to use one on my advice is always use a single quoted string And the off chance you need a backslash thankfully the rare I think they're used as the escape sequence because they're rare Again in life, you generally type the forward slash unless you're a windows person, right? Yeah, so I don't know how you keep track of when single and double quotes It's mysterious to me if I if something's wrong with my code. I change it to the other one I just start randomly going through single quotes and change into doubles because I don't know I can't keep track I think it's because well single quote means exactly this double quote means i'm going to have a think about it and stuff will change So inside the double quotes, it's like it takes two passes at it if you want to try to remember it that way so a single well But the place I got stuck on was the um spaces in When I wrote more bacon And it is as one of the uh things you could choose from my menu And if it was a double quotes it would interpret that that space and make that a separate name So I would have a choice of more and a choice of bacon A single and double would work the same there the important thing is there be quotes Oh, maybe that's what it was. Yeah, maybe there weren't quotes at all. Yeah, okay. Well, see I didn't even remember that correctly Quotes are going to be mysterious for life for me. I think but okay now I like now I like single ones and I'm never using backslashes got it Inside format strings, that's a good idea. Uh, remember that in a single quote dollar variable name does not expand Right because a single quote is literal. So if you type If you have a variable called Dollar x if you stick single quote dollar x single quote the output will be the dollar symbol and the x symbol If you do that in here Bart I need a cheat sheet difference You are getting on me one. Well, no, we are working towards a cheat sheet Remember that is my promised finale my grand finale for all this bar stuff is a joint big cheat sheet for Well, I didn't know that I don't know that you told us that okay great great No, you already gave me great praise about the idea last time. So I like the fact that you don't remember you've praised me before This is good. You get to do it again Anyway, yes, that is where we're headed to a nice big cheat sheet which is selfish of me because uh, I need one And I figure if I need one we all do okay, so where was I yes, okay So that all works fine. So that's our escape sequences out of the way plain text. Are you right? The meat these format specification thing are more bobs So they start with the percentage symbol So if you're using printf and you see a percentage symbol That's what i'm going to call a placeholder. The official name is a format specification And a format specification contains up to four parts Actually, there's a fifth part. I'm completely ignoring for this series. So remember I said this thing can do more than we're going to talk about so We have the option of having up to four things after the percent We can have zero or more flags We can have a minimum width We can have a period followed by a level of precision We must have a type So the types are As far as we're concerned the subset we care about are d for a whole number, which I think of as digits Right, so 10 is a d f for a floating point number. So 2.145 s for a string And percent for a percent Because we have the same problem as we have with the backslashes, right? The percent means we're starting off a format spec So what if I actually want to print out 100 percent? Without I actually need to have percent percent We're gonna have percent d for the number percent percent Right, okay Okay, so the simplest format specs are just a percentage symbol and the letter d f or s Right, all we're using is the is the the percent and the type But we have these other three things which we can use When we need them and I could explain them all up front, but I'm going to show you instead of tell you Right, I'm going to show you why we need them by having Some simple stuff. That's not nice and they will make it nicer So we're going to start with a very simple format string percentage d space percentage s space cost The dollar symbol percentage f new line character now in my show notes I mentioned in giant big bold text, so I wouldn't forget to say it and then I promptly forgot to say it Print f does not show of a new line character onto the end for you This means that you can use five or six print f statements to make one line of output Which is convenient because with echo every time you do an echo you get a new line So you can't build your string up in pieces But it does mean you have to remember that if you want a new line you have to tell it I would like a new line But I can see the value of that if if it would get really hard to read if you just had one giant long print f statement Exactly exactly. So it is actually very valuable to be able to break them apart But I I do often find myself with my bash prompt suddenly showed off way to the side is like, oh, I forgot to slash it didn't I Okay, well, let's rewrite the code and you'll know right away. You'll know right exactly. You know right away. So uh, so then we we have Three arguments after that. So five pancakes 5.5 I want a print case. So let's let's say it again because you said a whole bunch of words in between In his string, he's got percent d Is his first wait. I'm going to get the word correct format specification It's just percent d then he's got percent s cost And then he's got percent f which is going to be one of those floating points But he's put a dollar symbol in front of it Which will just should just be passed through as a dollar symbol and then he gives himself a new line And then he's got the three What are the arguments values? Okay Sure, let's call them values. Uh, five pancakes 5.55 Yes, which prints out five pancakes cost $5.5500 Okay, so the the five took the percent d because it's a it's a a digit It's a whole number and then you had to use a percent s to put in pancakes So five pancakes because it's a string and then you wanted a floating point for how much it costs So you put in the dollar symbol and the floating point Uh, ampersand f to get a 5.550000 Yeah, now It decided that floating point numbers should have Six decimal places six digits of precision. That's its default. I've just decided I don't want six digits of precision. I want I want two So how do I control money? Yeah, exactly. How do I control precision? Well, if we scroll back up one of the four things that we can put in there is precision, which is period symbol followed by a number So we oh, I like that. That's good syntax. Yeah, so you're gonna hate lots of other things Okay, let's stick with what I like don't don't don't remind me but this one's good This one I this one. I actually remember so let's update our that's update our format specifiers So that we have instead of just saying percent f we're going to make it percent period two f So if we do exactly the same thing but after the last one we now have percent period two f Now we get five pancakes cost dollar 5.55 Which is much better Great. So now let's do some bigger numbers. Let's break it again So earth diameter becomes equal to 40075.017 which is the number of kilometers that the earth is around its equator I checked So let's print f that so the first argument to print f is the giant big string the space earth space is space percent f k m space around space the equator Period slash n and then end my string And then I'm just going to pass it one placeholder or one value, which is dollar earth diameter Which is going to call it a placeholder. You already aren't allowed to use that word Yeah, okay one one more argument, which is the value that's going to get shoved into my placeholder Ha, there's the right word. I think I think for the audience you don't need to keep saying the spaces because it's a little harder to to follow it So it says the earth is percent f so that's going to be a floating point number Is percent f k m and you can just smash it right together because the kms is going to pass right through Around the equator and then you put a new line and you're shoving in the value as dollar earth diameter Which you just finished defining in the previous line Correct, which is going to output the earth is four point zero whatever to six decimal places kilometers around the equator So now we have two problems the precision is too high and Uh, where's the commas? How am I supposed to read this big wall of numbers? So first off we actually don't care about the you know, we're dealing with the size of the earth How's about zero decimal places? Well, you'll be happy to know that point zero just means lop them off. Don't care. That's a precision of no decimal places So that's easy enough to do. Great. So now we're down to four oh seven five k m around the equator That's still not right. We want our separators Now this broke my head for a bit because when you read the documentation on wikipedia It looks like the optional flag for the separator is the comma symbol, which would be nice It's not It's the single quote Which is not nice. I imagine it as a floating comma. It's the only way my brain is ever going to store the information There's an open air comma that helps So if we go back up when we have a look so we can have percentage symbol followed by optional flags Ah, okay. So the optional flags go before the precision So that means that it's percent Single quote point two f sorry point zero f because we want our zero Now this is where string interpolation gets in our way Because if we use single quoted strings, then the single quote will end the string So now we've got to use double quoted strings the tag goodness We don't need a backslash if you ever need a backslash and the comma separator you have a mess You don't have to do all sorts of escaping and stuff So this time i'm changing to i have a really annoying question go on in in uh France they use the comma for the decimal So how would the the French just have to use English syntax? No, no This is the magic so the print f statement doesn't interpret it as insert a comma It interprets it as insert a thousand separator and it doesn't insert a precision as insert a period It inserts it as insert a decimal separator. So when you're in a French version of macOS Yes, if you're in french back it will do the french thing Or if you're in belgian bash because the belgians do the same as the french That's localization. That's fabulous. Yes, so you'll be happy. There you go a little bit of happy joy. So if we now have our format string as percent single quote period zero f That will give us a floating point number with all of the decimal precision gone And the thousand separator so finally we get the earth is four zero comma zero seven five k m around the equator Which I can tell you is 40,000 because now I can see that it's 40,000 and not a wall of numbers Right, right, right. That looks that's fun. Yeah, it's not that hard now that I can think of it as a floating comma. I'm okay Yes, this doesn't makes me cranky. Why not a comma? I'm sure there was a really good reason somewhere somehow It makes me cranky anyway So the next thing that you can do You can actually use printf to make tables on the terminal So you've probably noticed that there are terminal commands that output tabular data And they do that they're probably written in c So they're probably using the c version of printf But they're doing it with printf because printf can take Remember, so we have if we scroll back up again, we have our four things Percentage sign optional flags optional minimum width optional precision type So the minimum width is the key to Giving us spacing so that things line up correctly Now it is a minimum width if you say I want this to be 10 y then you give it 11 Characters worth of stuff it will not truncate it It will go well. It doesn't fit So it does treat the width as a minimum if you if you say this is 10 y then you give it 12 It will print 12 Am I making sense so Yeah, it'll override the minimum because you gave it okay Yeah, it will overrun basically so the official documentation just calls it width And then it tells you that it will overflow So I in the show notes called a minimum width because a width that overflows is a minimum width It's not a maximum width, right? right so By default if you give something a width Obviously if I say I want you to print the string boo A width of 10 Well boo is three letters and I've said make it a width of 10 So then the question is what do I do with the other seven? Do I have seven spaces and then the boo? Or do we have the boo and then the seven spaces in other words? Where do I put the value in the in the width? I've just given it And the answer is the default is that if you specify a width everything gets right aligned not left aligned right aligned And is padded with spaces So seven spaces and then boo if I say I want a width of 10 and I pass at the value boo So it's right aligned padded with spaces So it's not Okay, if you said uh The width was 10 Is it 10 to the edge of the right align or up to I'm losing where the where the 10 is so the 10 is the four. Okay, so it is there are there will be 10 characters printed and the last Three the last characters will be what you passed it and anything it needs to pad it will be padding before So if you say I want this to be 10 wide and you give it four characters It will print six spaces and then your four characters By default Okay, sorry, I was using Bert's example and testing that now I understand I wish I'd use the number smaller than 20 I made you count a lot there So the fact that it's right aligned is interesting your example Yeah, so in my example I'm going to make a variable to hold our format string Because we're going to use the same format string for multiple rows of text So imagine if you're printing a table you could end up using the same format a thousand times Right if you have a thousand pieces of data to print into your table So instead of copying and pasting a thousand times or whatever you can save it as a variable because it's just the first argument So I'm just going to save my format as the string percent 20 s space percent eight point two eight period two f slash n So that's percent 20 s We know we know the first thing is the uh, well, we got to have the percent The second thing is the flags, but it looks like we don't have any Correct. We're not doing any any uh commas with apostrophes or anything. So you're saying 20 So that's the minimum width And then you're going to have a string And then you've got percent eight dot two f which means it's going to be eight characters right justified And it's gonna but it's going to be a Uh floating point with point two precision followed by a new line Perfect 10 out of 10. Okay Okay, so then in order to not muck up your terminal I'm going to put I use the semicolon to have two terminal commands on one line So it's just a print f semicolon another print f That's all that's going on here because otherwise when I copied and pasted I had my terminal reappear and my table wasn't pretty So it's print f and then we are quoting our format string because our format string contains spaces So it's print f space dollar row format And then the first argument is waffles wait print f quote dollar row format format. Yes And then our first value is waffles and our second value is 4.5. Then we have our semicolon print f Our row format again Pancakes 5.4 And when it prints out we get a right justified pancakes Followed by 4.5. Oh And then a right just sorry waffles 4.5. Oh pancakes 5.4. Oh And on a terminal would fix with font they line up perfectly And the first column is 20 wide and the second column is eight wide Um, I think it's nine One two three four well, there's a space there's a space between the two columns So there should be it should yeah Why is there a space because the percent eight is not I I intentionally put a space between the s and the percent eight If I wanted there not to be a space I would bash them together No, you can't do that. Oh, of course you can Wait a minute. So right now it says percent 20 s space percent 8.2 f you're saying you would write percent 20 s percent 8.2 f Yes, oh because that space is just it's just a string character being passed through just plain text I'm glad I Counted because that could matter Now a lot something you will see done a lot is the pipe symbol used to separate your columns Oh because then you really do get a table and then if you use dashes For some horizontal rows a few echo statements with dashes So not piping Okay, I was a little worried there that I was going to be piping one of these format strings into the other It's not a format string one of these Uh, shoot. Well, the whole thing is a format string, right? So you could say no, but that that's not what I meant Uh, I thought we were going to be piping one format specification into another format specification But it's just a string at this point. It is just a string character pipe with it. Yeah, precisely precisely precisely Context is everything context is king. Yeah So, huh that that really right so That's what it's doing by default That's not necessarily what you want for your default So how about we left a line our descriptions? The flag for left a line and I have no idea how you're going to remember this. It's minus So if we change our row format to be percent minus 20 s And then space percent dollar symbol percent 8.2 f So I've added it in the dollar symbol just because I probably should have done that on the first one Now I think about it. But anyway, there we go. So I got clever next time so The minus now means that our waffles and pancakes are going to be left aligned inside their 20 wide space So now when we print it out we get waffles space space space space space space dollar sign And then after the dollar sign the eight width of the floating point begins Then we have our pancakes dollar sign and then the eight width of that one begins okay um And it notice it is eight in total So the period counts as a character If it was a negative number it would count as well, right? So it really is a very dumb eight characters It's not like eight digits to the right of the period. It's not it doesn't it's not it's not thinking numbers It's just thinking characters, right? It's just there are a room here for eight things to go on the screen So eight things I wouldn't call that dumb at all that you You require that when you're aligning things that that a period should be a character. That's Takes out the space Yeah, yeah, that's fair Okay, minus I can kind of feel it 20 means shifted over to the right But if you want to shift to left you got to go backwards minus 20 Maybe if it works horrible. I need a money like a Florida comma for crane out loud bird. Yeah. Yeah anything that works for you The other thing you sometimes want to do with numeric data is instead of padding it with spaces You might want to pad it with zeros Because sometimes you actually do want to have like if you're building up file names You might want to have zero zero one zero zero two or whatever So you can do that with the flag zero Hmm That one actually does make sense So if we have the row format percent zero three d The first zero is the flag Because the width has to be one or more So so a zero will never be interpreted as a width because a zero is the flag Wits are one two three four five six seven eight That bothers me a little bit. I know it looks a bit weird, doesn't it? But it does work because if you print out One 20 and 300 we get them perfectly lined up as zero zero one zero two zero and three zero zero And you did that with percent zero three d Yes, so it's a digit It's going to be three wide you could have made it Five wide I could have and then I would have had two more zeros padded in front of each one Wait Why? Because if you say five and we're padding with zeros Then there will be oh, you're telling me zero three is saying how many zeros to pad with no. No, it's just Zero means pad with zeros three means how wide? So zero five not not how many digits you have width is How wide the column is we just finished saying that correct and instead of padding with spaces. We're padding with zeros I don't like this at all. So is it minute. How do I make it be a width of 20 and right justified? Hey, then you would just say Zero two zero zero I'm gonna write justifies what you get by default. So No Wait, but I think I don't understand. So it says percent zero three d You're saying the zero says we're going to pad with zeros and we're going to make it three Characters wide correct the column not the column width, but the the number will be three digits The placeholder shall hold three characters on the screen And the there's no such thing as a placeholder That's not a word. That's not a word. We're live format spec shall be three characters wide The output from the minimum width But that's not minimum width Yes, it is But we said minimum width was the width of the column not of the number of digits in what you're looking at Those are different with numbers No, there are exactly three characters zero zero one that is exactly three the width is three The only thing that's changed is that the spaces are now zeros if you take the zero I it would be space space one Space two zero three zero zero Okay, but how do I let's what would the syntax be to make it be right justified? We want it in his right column width We want the column width to be to be 20 Okay, oh, you're saying that in order to have these this this padding of zeros They have to be part of the width Okay, so when you make something 20 wide the default is we fill in the gap with spaces The zero just means don't fill in what spaces fill in with zeros Okay, so that's that's different than just saying there's a leading zero in the number These aren't really numbers. These are padded places To make up the width That's a that's a little I was thinking a lot of times you want numbers to to You know to look correct to have the same number of digits Uh, but in this case they also define the width It's a little just a little salty. Yeah, okay. Yeah, okay. I understand it now. I don't like it, but I understand it Now if you mix positive and negative numbers things can get out of alignment again So what do you do if you have a mixture of minus and positive numbers? Well, one of the things you can do is explicitly prefix the positive numbers with a plus I think that looks ugly, but I'm sure there's a reason I'm sure there are places where you would want to do that So you can have the flag plus to say prefix my positive numbers with pluses So then if you do that, let's say you say percent plus d And then you ask it to print out minus one zero one one you get minus one plus zero plus one The plus zero might irritate the other gel the other gel would get cranky at the plus zero, but anyway um Or a nicer solution might be to pad with spaces so that a positive number the other gel it's still gel of kent It's the it's the same gel. Oh, so it is. Yes. Apologies gel Keep our gels correct Something that's more practical to want to do is just to have a space in front of the positive numbers so that they line up They line up. Yeah, and you can do that with the Flag oh you're gonna love this You can use the space as a flag Oh, come on. I know so percent space Means Percent space d means I want to digit and the flag is the space and it looks like you're separating it, but it's not The percent space d is all because it goes as far as the type which is d It makes my head hurt and it knows and it knows not to apply that space to the minus Yes, because that's what the yeah, that's what the syntax. So that's the meaning of the flag is pad positive numbers with the space When you see your command and you see the output right afterwards it makes sense at that instant in time But if I was looking at that without your output, I'd be going what? My advice when using printf in your own code is to comment generously So that future you knows what you're doing And if you're going to read someone else's code that uses printf have the have the manual open Just just have the docks open. You're going to need them I promise you you will need them because you'll be looking at a percent space. What what what? Because you can have as many flags as you like as many flags as make sense. You can shove them all together So as a final example, we have the wonderful format percent space single quote period two f Right. So percent space means I want to prefix my negative numbers with a space Mm-hmm. Oh sure. I've just lost my place in the show notes for a terrible time Uh, the single quote means I want thousand separators The point two means I want a decimal precision of two and the f means floating point So if I run that with minus one two three four point five six seven eight and nine eight seven six point five four three two I get minus one comma three two four point five seven. So I've truncated by two. I have my comma and on the next line I have space nine comma eight seven six five six point five four again truncated to two decimal places with a space And my comma not truncated rounded Yes fair red red and also also rounded down So it was one two three four. It was negative one two three four dot five six seven eight So they rounded to a smaller number. They rounded down. They went in the down negative Uh direction. Yes, actually the five seven was rounded as well in the upward. That's the one I'm talking about. Yeah I'm saying it went it went more negative That that is oh, sorry. Yes, because in my in my time Time adder application that threw me because it didn't uh round doesn't round down in uh, javascript So it was getting bigger. It was like wait what that took me a long time to find that one Oh, that is weird Yeah, I had to do some jiggery pokery to fix it. I hope I said that correctly But it was one way or the other it was doing it the opposite of what I thought it should Interesting bad interesting but interesting Um, and then one final little tip. So the precision operator obviously makes sense with decibel numbers And I did tell you that you specify a minimum width What if you actually need to make some text not break out? What if you want your text not to smash through? You use the precision operator to truncate strings So if you yeah So if you want to have a string be exactly three characters You would say 3.3 s 3.3 so a max a minimum length of three And and then a precision of three Which means if it's longer than three chop it off And that will give you exactly three That's so annoying because now you're you're taking decimal syntax and and applying it to string. Wow, but I just have a word highly efficient language You weren't working with as you said It's information dense. There are very few characters in these format specs But there's a lot of meaning in those very few characters like a regular expression It says a lot would very little which is powerful And very confusing when it's other people's code Yeah, yeah, definitely. Uh, those uh, those three letters and those digits they're they're doing a lot of work They really are doing a lot of work. So the final example in the show notes. We have Percent minus 3.3 s space percent 2d And we're giving it monday 5 tuesday 11 And that ends up printing out a nice little table of m o n space 5 Q 11 and it's all nicely aligned The first row left aligned not that it really matters when you truncate us Um and the second right aligned As I say, you can get so carried away with this so carried away with this Usually to be honest the way the way it normally works in real world is you start with just percent s and percent d or percent f And then you run your script and it won't look right. And then you go, okay What do I need to change and then you'll start to throw in your flags and your precision until you get what you want That is generally how I would advise doing it. Oh, you're on mute. Alison I am I took a drink of my water. My ice makes noise One of the things I did was to help with this was I used my my screenshot tool that I'm testing right now called shatter To take a screenshot of the syntax that you gave us so I've had it floating So no matter how much I scrolled through the show notes I keep going, okay flags are first then min width then precision then type got it. Yeah Yeah, and that I mean that is it. So final thoughts just Jill's wonderful message serves as a fantastic reminder that the community drive this series And the the the further we've gotten into it the more into the hundreds we've gotten the more the community is affecting The flow of things right the things the community find interesting I spend extra time on When the community get confused about something I loop back and when the community have a great idea I will very often take it on board as This entire episode took a whole different turn than what I planned because of Jill's message So potfee.com forward slash slack is where you can hang out and send me messages of your own Or Allison very good lots of people in there having great fun Yeah, the program based stealth Channel is probably the most active other than delete me where we just goof around throw random stuff. Yeah And then the second thing I'm hoping you appreciate is just how powerful printf is it really is It makes it possible to write some amazing outputs through the terminal And like pearl's regular expression syntax is a digital life skill These percentage symbol things They show up all over the place now that you know about them look out for them And just like when you buy your first ev you'll suddenly see evs everywhere Once you know these percent symbols You're going to start seeing them all over the place including in security alerts for apple routers from time to time so anyway, that is That is hopefully a new life skill and I'm going to end with a challenge So I had to I had to think long and hard about this and I've teleported us back in time a bit We're going to set our menu aside And way early in our bash adventure we did loops And the tradition for making loops and setting homework is printing in x times table Well tabular data sounds like something that maybe we could have some x times data in so I would like you to write a new shell script for printing out a nicely formatted multiplication table I would like your script to require one argument which is going to be the number whose table we print out By default, I would like you to print to multiply that number by one two three four five all the way up to 10 I would then like you to accept two named optional flags Minus lowercase m for a different minimum. So instead of it being from one to something be minus m to something And an uppercase m for a maximum because minimum and maximum start with the same bloody letter. So I figured minus m minus m So minus lowercase minus uppercase to replace the 10 for the uppercase For the upper limit. So that way you can make your table go from, you know, minus four to five million or whatever you like Then as some bonus credit I would if you have the time and the inclination If and only if standard out is connected to a terminal I would like you to send your output through less Oh, there it is. There it is. So if you do the 100 times tables from minus 1000 to plus 1000 I think we should have that with a space to go page to page Okay So there we go you get to practice everything we talked about I hope Yeah, yeah, that sounds like a fun one now. I assume we're allowed to go use our previous homework as a starting point Oh, yes, I certainly will be I like that assignment. I was good at that one. I didn't do so good this week, but uh I'll be back in it. I think this will be a lot of fun. This looks I I like this alignment stuff You know, I like tables. I like organizations the more I wrote these show notes the more I thought Allison's going to like this one I also knew you were going to hate some of the syntax so I I preemptively Sort of nipped it in the bud But I knew you wouldn't like things like the single quote because I don't like it Silly, right, right, but I didn't get the design that I just have to tell you Right. Well, that is it. So until next time lots of happy computing If you learn as much from Bart each week as I do I'd like you to go over to let's dash talk dot i e And press one of the buttons over there to help support him He does 98% of the work here I'm just the stooge that listens to him and asks the dumb questions If you go over to let's dash talk dot i e you can support him on patreon You could donate via paypal or you can use one of his referral links I really hope you'll go over and help him out in the meantime You can contact me at pod feet or check out all of the shows we do over there over at pod feet dot com Thanks for listening and stay subscribed