 Well, it's that time of the week again. It's time for Chitchat Across the Pond. This is episode number 773 for July 8th, 2023, and I'm your host, Alison Sheridan. This week, our guest is Bart Booth Shots with Programming by Stealth 152 Part B. We're back. We are indeed back to finish where we left off, only we left off in the middle of it. Yeah, we did it weird last time. We did the hard bit at the start, the easy bit at the end, and then we left out all the meat in the middle. So let's fix that. But I got to tell you, I think it was a fantastic decision because I understood the episode two weeks ago. Had we done it, had we tried to cram this in, I totally would not have understood the meat. And the way you've rewritten the meat, now this is going to be so much better. I've pre-read the show notes, and I'm telling you, I think I understand it. So we're on good footing today, I think. Well, let's try to capture the momentum then. So I sort of asked you to put a pin in it last time, describing my sample solution, because I made two uses of a new terminal command called X-Args, and I told you, put a pin in it, we'll come back to it later. Now, I hadn't realized later it will be two weeks later, but anyway, put a pin in it, we'll come back to it later. So we are going to come back to it, and we're going to use the bit we skipped over in the sample solution last time as a worked example for X-Args, but we're going to spend a little bit of time making friends with X-Args first, and then we're going to see this particular use of X-Args. It's a real Swiss army knife of a command, and once you know that it exists, you'll start to see it on Stack Overflow Answers, and you'll start to see it everywhere. It's like until you buy an EV, you don't think there's many of them, and then you see them everywhere. Until you know about X-Args, you think it's obscure, and then you see it everywhere. X-Args all over the place. Interesting. Yeah, I don't remember having ever seen it, but now I'll keep my eyes peeled for it. Yeah. So the X-Args command's job is about processing arguments, and so to help us actually see what X-Args is doing, we need a script that's going to be very, very obvious, show us the arguments. So we could send the stuff to Echo, and Echo will echo each argument one line at a time, but if there's trailing spaces and stuff, that's not going to be obvious. So I wanted to echo my arguments in such a way that it was spectacularly obvious what was going on. So if I've written a little script, very imaginative and aimed, PBS-152A Arg printer, and it just loops through the arguments the script gets, and it prints them out, and then it starts it with the number of the variables. So $1, then a little arrow symbol made up of a minus sign, and then one of the chevrons, and then a pipe. It's like, this is an edge, then the content of the arguments, then another pipe, and then the reverse of that. So you can see $1 is between these two pipes, and so it's really obvious. You've just, you've formatted it to say, this is $1, look here. Yeah, and the same for $2, 3, 4, 5, 6, etc. And so the idea is that it will show us leading and trailing spaces, and to prove that point to you, we can run the script, blah blah blah, print args at sh, with the string first args, with just the space between first and args, and then space, and then a string starting with a space, then second space arg space, and then ending the string. And then you will see that first arg gets printed with the vertical lines touching it, and second arg very obviously has its leading and trailing space. And that's important to us for what we're going to do later. If you're curious how the script works, it's quite short. What I do in the script is- Can I pause you really quickly? You can. I'm actually having trouble figuring out, since we've got the meat in the middle sandwich we're talking about here, you don't appear to be starting it where it says introducing X args. You appear to have started somewhere else. No, the only thing in introducing X args is the note saying we jump to here, then I'm on boot first, ta ta ta. Boy. Did you do a pull? Yeah, I did. Let me pull again just in case, but I did and I'm on- Are you on the branch whip or are you on the branch chain? Oh, hang on. Are there- Okay, I'm a little confused now. This is going to make for great audio. Um, I appear to have seen two spots where pbs-152-whip exists in my little get cracking tree thing. Well, you should see one under the local and one under the remote. Yeah, but I'm saying in the, in the, in get cracking it has this nice visual tree that shows you everything. And there's pbs-152-whip at the top where it says fixed typos, which is the one I did on a different computer. And I, but I appear to have checked out a different one. So there's probably push or pull arrows. Bart, they have the same name. They would do, but- Okay, so it says a local pbs-152-whip already exists. So let me reset local to here and see how this works. Yes, that was the problem. Okay, that's kind of interesting because, because it was pbs-152-whip two weeks ago and it's pbs-152-whip this time, it confused, it confused things a little bit and get cracking. Okay. A push or pull probably would have solved that you may have lost your typo fixes there, not sure. No, no, no. I got them because I pushed them from the other computer. No, I'm right. I'm all caught up. You're all caught up. I don't know that that will be useful to the audience, but here we are. So we are, you are now talking about your script. Okay, good. So it's not a long script, most of it is comments really, but it does one mildly clever thing so that, you know, arrays are indexed from zero and arguments are indexed from one. The first argument is $1, the second argument is $2. So when I shove the array, when I shove the arguments into an array, the sequence number is wrong. So what I did was I put an empty string followed by the arguments into the array. So now the array has a placeholder of nothing and then the arguments. And this is an array we're going to loop through to build the argument list. Exactly. We're going to loop, we're going to loop, not over the array, we're going to loop over the sequence from one to the length of the array because we need to print our dollar and we need to print the actual value. Oh, that's right. Okay. So for I in dollar sequence, space one, space dollar, octos, or pound, whatever we're calling it this week. So that's going to send me the numbers from one to the length of the array. So for if we have two arguments, it'll send us one, two. If we three, it'll send us one, two, three. And then we just echo out backslash dollar, which is print me the actual dollar symbol, dollar I, so print me one, two, three, whatever, then print our arrow or pipey bit. Then we print the element of the array that is, you know, so dollar curly brackets, args array, open square bracket, dollar I, close square bracket, close curly array, that lovely syntax we're getting at a particular element in an array. And then we have the reverse of that to close it off. So the only real magic sauce here is that empty string at the start of args array. Just, you know, so it's easier. I was kind of proud of myself when I looked at that, I went, oh, he needs it to be one. Aha, perfect. I could see it. Okay, good. So we can see that it works. So that's kind of all there is to it. So now let's move on to why, you know, just to, just to say it more explicitly, he's got, he has a command to, you know, run this little shell script and he's got first arg, and then quote, space, second arg, space, unquote. Yes. You did that for a reason, right? Which then shows us in the output how well we can see any leading and trailing space. Okay. So those, those leading trailing spaces inside the quotes are visible and we learned the fact that, that this is going to allow us to visualize, never mind, I'm skipping ahead. Yeah, we're basically, we're going to use this to visualize how the arguments look because x args job is to manipulate arguments. So to see what x args is doing, we're going to use x args to send things into this script. And then this script is going to be like a little x-ray machine to show us what's going on. So, okay, what is the problem to be solved, right? The terminal is this collection of little Lego bricks and each little Lego brick does one thing and does it well. So what is the x args one thing? What is its trick? What is its one hit wonder? Its job is to bridge a gap, right? So we know that we can manipulate standard input and make it go, you know, we can, we can send stuff to standard input using terminal plumbing, as we've colloquially called it. We can take it from a file and use the arrows, the chevron to put it into standard in, or we can use a pipe to take the output of one command and make it standard into another command. So any command that takes its input from the form of standard in, we know how to send stuff to it in a pipeline. But what if the command that needs to come second or third or fourth, basically not first. You have a pipeline and there's a command that's not first and you want the input from before, but the command does not accept standard in. The command wants arguments. How do you bridge the gap between I need arguments and I have standard in? Well, x args crosses standard in two arguments. So it crosses the streams is how I like to think of it. That's how I remember this job. A little bit slower for me on that. So, excuse me, standard in is can't be arguments. And if not, that's the leap I don't quite catch. So when you're running a command, when you write a script, you have standard in it is a thing provided by the operating system. And you have $1, $2, $3, they are things provided by the operating system. They are not the same. So if you are using your own script, you can write your own script to take stuff from standard in if you needed to. But what if you're using a command like printf? Printf does not accept standard in. Printf needs you. So you have printf, the first argument is your template and the second argument is your substitution value and the third argument is your next value and your next value. So those can't be standard in? No, because if you look at the man page for printf, it does not read standard in. Okay, okay, I got you now. So basically you have a round plug and a square hole. It's basically the problem. Or no hole at all in that case. Or no hole at all, right? Or the other thing, of course, is in the case of printf, if you need five values, like let's say that your template has five placeholders, then you need to give it five values. How do you get from standard in to five different values? Right, right, right. Well, so XARG's job is all about taking standard in and making it be arguments. And that allows you to bridge that gap so that you can get things that are standard in over into arguments. And so it really is just a swap around sort of a command. So the syntax is very straightforward. XARG's, the first arguments to XARG's is the command you want to run. So if we're trying to use printf, then the first argument will be printf. And then any other arguments that you want to hard code into printf or whatever, you put those next and then you stop. And then whatever was standard in is going to get added after those initial arguments. And then XARG's is going to call your command. Okay, so XARG's, and its first argument is the command you're going to run, like printf. It might have some initial arguments that are part of that command itself. And then it's going to reach back and get whatever XARG's created and shove it on the other side to be the rest of the arguments. Yes. And when you say reach back, it's from standard in. So the rest of the argument are whatever was in standard in. Because XARG's takes, because XARG's does take standard in. Yes. Okay. Yes. That's, yes. That's his job of life. So the, it's, it's like a square to round adapter. So its input is standard in and its output is a command with args that it has run for. XARG's is a dongle. It's a dongle. No, genuinely, it's a terminal dongle. It really is a terminal dongle. So to show you that in action, let's run a command. So we're going to, we're going to make standard in be a very simple string. So we're going to say echo and then inside double quotes so that we can capture it all nicely. We're going to have std in underscore arg one space. Single quote std in space arg to single quote and then end our double quotes. So the string that's going to be in standard in is std in arg one space and then single quoted std in space arg two. So we have two arguments. These are just names you created so that we can tell them apart when they're in the output that this is the one from standard in argument one and standard in argument two but you've used an underscore in one case and a space in the other just so we can see that they both work. Yes. And you will notice at the moment the space I have quoted. Right. And then we pipe that. So echo writes the standard out. The pipe turns it into standard in for x args. So x args is standard in is that string with the two arguments. Then we have x args space. The name of our arg printer script space initial underscore arg one space open a single quote initial space arg space to close a single quote. Oops. Sorry. That second space should not be after arg two. I changed my mind on that. So initial space arg two fixing now. So hang on. Why did we have to explicitly put those names in at the end? Well, I'm sure you were the initial args. What's coming. They're the same name as the strings that you passed. No. Initial arg versus std in arg. Oh, I'm sorry. Okay. So. Okay. All right. Oh, so I'm sorry. I'm sorry. I'm being dense. I just finished making you restate it. We've got x args, then a command the initial args, which in this case you called initial arg one and initial arg two. And then what's going to get shoved in afterwards is the stuff from standard in that x args grabbed, which is the standard in arg one and standard in arg two. Correct. And so when we run that through our script, what we see is that we get back initial arg one, initial arg two, std in arg one, std in arg two. So that is the order they come in. Great. Great. Okay. Okay. And that is right. Entirely equivalent to running our script with the arguments initial arg one, initial arg two, std in arg one, std in arg two. Right. If you run that command without the x args, it is just swap a rover. You can see it is exactly the same as running the script with the four arguments. X args just assembled it for us. Yeah. Yeah. Okay. So we can see that x args, x args basically treats standard in as if you had typed it on the command line. So it breaks the arguments apart on spaces and it respects quotes to group together. So if I didn't quote initial arg two, then I would have lost the, that I would have seen, that I would have come in as an extra argument, right, because it would have broken on the space. But by quoting it, it does, just like it doesn't determine. Basically, I'm saying it's like the terminal. Your quotes stop the spaces breaking things. Right. Right. Okay. Over-complicating it by saying it too often. But it's slightly cleverer than the terminal because a lot of terminal commands breaks stuff apart with tabs and or with new line characters. So as well as obeying the normal terminal rules of one or more spaces separates my argument, it also says, yeah, a tab, sure, that's a separator. New line character, yeah, fine. I'll separate on that too. And that means that commands like LS, right? If you do an LS slash by default, LS slash, just show me, list me the content on my root directory. You'll see that it gives you a multi-column view, you know, application space, users, actually it's applications tab, users tab, core, home, SBN var, right? They're tabbed across on one line and then there's a new line character. And then there's another set of tabs and then another new line character, depending on how many you have. So if you run that through X-Args and pipe it into our arg printer, you will see that it has successfully separated all of those, so applications, library, system, users, volumes, bin, they're all properly separated because the tabs and the new line characters were like, sure, no problem to me, I'm Mr. X-Args, I'm all smart. And so it breaks them all apart. Okay, so, and the command again for those listening is LS space slash, which is what he did before and then he pipes that into X-Args and then sends that to the shell script, okay? Yeah, yeah. And so X-Args is transformed. So that's good and it respects tabs and spaces and new lines, that's repeatable at least to know that. And useful because a lot of terminal commands spit stuff out separated by those characters. So it's generally very useful behavior. These things have been around since the 70s, they've had time to become useful and that is certainly an example. But, but, but, but, but. When X-Args was new, no one put spaces in file names because it broke things all over the place. And so as long as you don't have any spaces in your file names, X-Args behaves really well when combined with LS. And it's not true here in the 2000sies where we have spaces all over the place because we mostly make our files in the GUI. And in the GUI, it's so much nicer to call it MySpace document than it is to start camel casing and dashing and underscoring. So a lot of our files have spaces which X-Args will promptly see as a separator. So I have made a dummy file inside the zip for this installment called namewithspaces.txt. And so if we do the LS command on our, the folder for the installment, and then we run that through X-Args into our printer script, we will see that we get back five arguments. Name with spaces.txt, then the script, then the sample, sorry, then the sample solution, then the script we're using to printerArgs. There should only be three. Name with spaces should be one, not split over three. Sugar. How do we deal with this? Now you might think that logically the X-Args command would have a flag to say I would like you to use tab as a separator, or I would like you to use new line as a separator. And that's half true. That's true if you're on a modern operating system that's not the Mac. Because Apple... Wait, wait, wait. You can't call Mac Apple not a... Oh no, Apple is modern. The problem is that every other modern operating system except for the Mac. If you're on something, it all bets are off. But if you're on something, you all bets are on unless you're on a Mac, in which case you are on a modern operating system. But no, you still can't play. So if you want to be cross-platform, I'm just not going to tell you about the stuff that isn't cross-platform. And so we're going to have to figure out a different solution that is genuinely cross-platform. And the good news is there's not just a way to do this. There's in fact many ways to do this, which is very common on the terminal. I'm going to share two ways that work. I know for a fact there are more because when I Googled it, there were all sorts of other answers coming up on Stack Overflow. It's just they looked more confusing and I didn't fancy explaining them. So I went with what I think are the two nicest solutions. So the first thing we should know is that we do get a tiny bit of control over the separator on every version of XRX. So by default, it's spaces, tabs and new lines. So basically blank things. That's the default is if it looks blank, it's a separator. There is a minus zero. And it's not a minus capital or lower case. So it's a minus the digit zero. And that says the separator shall be the null character. This is a character that exists in ASCII and everywhere. That is the character that means no character. It's a bit like zero in the number system, right? Zero is a number that means no number. The null character is a character that means no character. It's used on, if you're programming in C, that's how you end a string. You put the null character in and that tells C to stop reading memory where at the end of the string. So it is used in a lot of places. It's used at the end of files and some file systems as well. So the null character, we can't type it because our keyboard doesn't have a key for null character. But we do have backslash zero, which is the escape code for the null character. So if you want to talk about the null character, it's backslash zero inside interpolated IE double quotes. So like backslash n is a new line character. Backslash t is a tab. Backslash zero is the null character. So we do have access to it. So if we say minus zero, then x args will treat everything that's not the null character as part of one argument until it meets a null character and then it will start the next argument until it meets a null character and then it will start the next argument. So if you have things with spaces, no problem. Question is, how do you make LS spit out null characters? Well, the answer is, I'm afraid to say you don't because LS doesn't do that. But if you read the man page for x args, it actually says that x args is designed to work with find. And it actually, it literally, there's a paragraph in the man page that says that the minus zero flag in x args is designed to work with the minus print zero flag in find. So they're a little matching pair. They're friends with each other. The find command is something we've covered at Taming the Terminal. It is a command for finding files. And by default, it finds every file. So if you say find dot, which is the current directory, it will find you every file in the current directory. That's kind of like LS really, isn't it? Right. So we've sort of gotten there. So the easiest thing to do is to say find space dot minus print zero, which means find is now going to output the answers to what's in the current directory with these null characters between every file it finds. We pipe that to x args minus zero. So x args is now looking for that little character. And then we send that off to our pretty printing script. And it successfully prints out our files in the format find puts them in. So it tells us that our folder contains dot, which is the current directory, because we told it search dot, and it prefixes everything with the path. So it's dot slash whatever. But I mean, that's not the end of the world, right? That they are valid file paths. That's pretty good. Yeah. Sure. So I'm going to count that as- And maybe even more information. Depending on what you're doing, it might actually be better. So I'm going to count that as a viable solution. There is another way. We have a link in the show notes to taming the terminal installment 20 where Bart does start explaining all about the find command. Oh, I'm so happy you noticed I forgot to replace my triple X with the actual value. No, I figure whoever finds it first should just do it. Thank you. I thought I'd done them all, but I obviously missed one. Okay, so that is a solution. Use the find command. And the find command is actually really powerful. So if you wanted to do something like count how many lines of JavaScript I've written, you could use the find command to find every file name that ends in dot j s and point it at your home directory or maybe point it at your Git directory where you check out your Git repos, and then shove that into XRGs and then into WC minus L. And then it will count, right, only the lines in your JavaScript files. Interesting. That's as long as you're not using Git to look at other people's repos. Sure. So I will now take credit for everything anyone has written in the PBS challenges for the students of programming by stealth. I guess a more realistic thing would be, you know, you're working on a project and your boss says, so how big is this project? And I've had managers ask me these kind of questions. I mean, if you were to just have to rewrite this in a month, how much work would that be? Quick, quick, quick, you know, find dot minus name, and that gives us Perl files, you know, dot PL, WC minus L. That's 20,000 lines of code, boss. Oh, maybe two months. Anyway, I've been there doing that. So the find command, you can also use find to do things like everything I've modified in the last hour, all these kind of things. So the find command is actually a really good way to gather file paths. So the fact that you can use the find command with the minus print zero and then shove it into XRX minus zero is genuinely very, very useful. So that it's really nice that they work together. So that's one solution. I'm going to count that one as tick. But there is another more general approach you can take. So a lot of terminal commands, even if they don't support this null character nonsense, will quite happily print things out one line at a time. So basically printing it out on a line per item, which then transforms our problem. What we need to do then is just change every new line character to be a null character. Well, if the command itself can't do that transformation, the terminal is made of Lego bricks that do one thing and do it well, is there a brick that translates one character to another? Well, there is. We've mentioned that in passing a few times, the to command for transliterate, the to command takes two arguments, a character and another character. And it takes standard in, finds the character, the first character, replaces it with the second character and pops it out to standard out. So it's basically it takes input. So we're going to say to space slash n slash zero. So it's going to take standard in and every new line character becomes a null character and then it shows it out to standard out. So you can just stick that into the middle of your pipelining just between the LS and the XR-minus zero. And now XR-minus zero is getting null characters. So wait a minute. So we're replacing new line characters with slash zero, which is a way of telling it we mean a null character, but we had spaces. Those weren't new lines. Ah, yes. We have one more little trick to perform here. So we're almost there. So if we do that by default, remember that LS was showing us a few columns and then a new line character and a few columns and then a new line character. So if we did this trick now, we would get the first argument would be three or four files and then the second argument would be three or four files and the third argument would be three or four files. So we need to tell LS to be a little bit cleverer. Now you know that if you do an LS minus L, it'll give you a long listing and then it'll show you one line per file, but a whole bunch of glop that you don't want. Does LS allow you to go one item per line without the glop? Yes, it does. LS minus one. We'll print you out the listing one item at a time with no glop after it. So if you take LS minus one, put that into TOR and that into XRX, then you get the perfect outcome, which is basically namewitspaces.txt is the first argument, PBS-151 challenge solution is the second argument and our arg printer as the third argument. Hang on. Oh, because we've told it XRX minus zero, which is to only look for new line characters, don't look for spaces. Now, so the minus zero means look for the null characters, right? But remember that. Okay, let's start at the start of the pipe. Let's not start in the middle of the pipe. Hang on. Hang on. Minus zero, I thought meant look for the null characters. That is exactly correct, but you said new line a second ago, so I corrected you. Yeah. Oh, okay. So XRX minus zero is saying only look for the null characters, don't look for spaces. Correct. Only look for new line. That, I'm sorry, I did it again. Only look for the null character, but in this case we've transliterated, we've replaced the new line characters with the null character. Yes, we have. So when it looks for the null character, we get the new lines as the only way it separates no other way. Precisely. So ls minus one dot into t or slash n slash zero into XRX minus zero, and then over to our printer and we get the perfect output. So I actually had to look up the word transliterate, even though you said you've already taught it to us before, and it's such a fascinating word that needs to exist. Write or print a letter or word using the closest corresponding letters of a different alphabet or script. So names of one language are often transliterated into another. I thought that was fascinating that, boy, we have a complex world that we had to come up with that word. We do. And actually the t or command is slightly clever than what I've just told you. So I've given you one character to one character. If you put abc as the first argument and 123 is the second argument, then every a will become a one, every b will become a two, every c will become a three. Oh, so we could make leet speak. We could make leet speak. In a regular language. We could also very easy do a Caesar shift. Which is an early coding or yeah. Yeah. So basically you say that I'm going to slide the alphabet by x and then so an a moves five forward, a b moves five forward. So with t or you could just do that as a simple command. So abcde becomes, you know, fge whatever and loop it around at the end. Yeah. So the t or command is actually quite powerful. Yeah. Very useful. So we have two perfectly good ways of getting our stuff to XRX when it has spaces in it. And I promise you there are more. A quick Google will give you many more. But these, these are simple to understand and they work cross platform, which is my big thing. So now let's look back to that poor pin that's been sitting in our sample code for our two weeks at this stage. So we were working on printing out our very pretty multiplication table. And we needed to get the lengths of things so that we could make our tables be nicely padded that no line was longer than the other. So we needed to work out lengths. And particularly I needed to get the, there was all sorts of length ones I needed. But the one I told you to put a pin in was plen, which is the length of the product is equal to. And then we open up a dollar sign and we wrap our entire command in the dollar sign because we want the answer from this giant big command to go into the variable plen, right? So the question really for us is what's in the giant big command? Well, we start off with an echo where we say echo and then we say dollar N, which is a number, star symbol, dollar M, which is a number. And we pipe that to the basic calculator BC. So that's going to be some mathematics, right? So for star 11 or whatever, that's going to go to BC. And then BC gets piped to XRGs, print F, and then the string percent single quote D. So percent is start a placeholder. The single quote is, I would like you to use commas to separate thousands. Remember we have the anti-graph comma is how I remember it. It's like a comma that stuck to the ceiling. And D is for I want it as digits. So no decimal places, right? Just a whole number. So whatever the output of the math is, is now going to XRGs where the, sorry to print out for the first argument is this pattern we want. And the second argument print F needs is what is going to be in percent D, which of course has to be the output of the calculation. So therefore XRGs is taking its standard in, which is going to be a number like 42 or something. And it's putting it in as the second argument to print F. So print F is going to print out 42 nicely formatted. So without doing this, since print F can't take standard in, you would have to have stored everything we just did into a variable and then made that the argument to print F. The second argument to print F. Correct, that's it exactly. And then we want to say, well, how long is this? So then we need to pipe this to WC minus C, which I'm telling you is a character count, and that is true if you stick to all the fashion D stuff. I think we had a little discussion on the PBS Slack, which is an amazing place, podfi.com, fold slash slack. Yes, I noticed I asked the question, why does Bart use WC dash C? Because dash C is not, is not the character count. It's the character count in the old fashion sense where a character was eight bytes. So if, if you stick with, well, in this case, we're counting digits and things. So it's definitely right here. But if you put an emoji in there, it will break horribly. If you put some sort of a strange Cyrillic character or some Hebrew character, it will break terribly because they're actually two characters. Diacritics will break. But for the case of our math, it's fine. And in my brain- But I don't understand why, why a character count being eight bytes? Why is that not eight? I mean, you have to, you have to know that, that a character is eight bytes and care, like why do we care that it's eight bytes? Why not just use dash M, which is what word count was actually the- Well, it's morpheme count is where dash M comes from. Because minus C for character works in my brain and minus M does not. It falls out. Okay. So if you would like to be correct and precise and have stuff not break, use dash M instead of dash C. Yes, which stands for a morpheme. So if you have UTF-8 or UTF-16 and you have like an A with that funny squiggle the French put under things, that's technically two code points. Well, no, the Cedilla goes underneath, that's a C. Oops. Okay, a C with the funny squiggle, the Cedilla. That's actually two different characters in UTF. It's the C and the diacritic. And together they form a single morpheme, which is a thing you as a human care about. And so the minus M counts the morphemes, which I just can't remember. Are you okay if I put a little aside right in there or something saying- Sure. If you want to- Okay. Yeah, absolutely. Yeah, great. I was kind of proud of myself for finding that, by the way. I read the man pages. Did you notice that? Look at me go girl. So at this stage, we've counted the characters in our pretty printed number and then we pipeline it to XRX one more time and we don't give it any more values than that. We just pipe it to XRX and let it dangle. What's going on there? Well, let's break this down piece by piece. So in order to play along here, let's first just declare that N is going to be three and M is going to be 14. So if you shove those two into your batch, just N equals three, semicolon M equals 14, then you now have the numbers. So if you then just echo out our string and pipe it to BC, you're going to see that it outputs 42. So when I said that after we do the BC, the value of standard out is 42, you can see that's perfect. So you could then save that to a variable called prod and say prod becomes equal to dollar sign, open round bracket, echo our string to BC and then print F, our format string, percent upside down, comma D dollar prod and it will correctly print out 42. Okay. No, it won't. Yes, it will because sorry. Yes, it will because we're not counting them yet. We're just pretty printing it and the pretty print of 42 is indeed 42. So then we shove. Okay. So yeah, right. Everything works absolutely fine as we build up this pipeline piece by piece by piece until we do the WC minus C. And what the WC minus C outputs is space, space, space, space. I didn't count the spaces. I think it might be eight of them. It outputs a whole line of spaces. And then it outputs the count, which is two. So there are only two characters. And it does that for all sorts of weird reasons that I don't agree with, but I'm not going to go into. And if you try to do math with space, space, space, space, space, space two, if you try to do a plus or something with that in bash, bash says and goes, oh, that's a string. So I'll concatenate it. So when you try to do math with space, space, space, space two, say, you know, add one or something, you're going to end up with the string space, space, space two, one, not three. So those leading spaces are really causing us trouble. And so this is where XRX comes into play for two reasons. So I haven't been massively explicit about it here, but I have intentionally said it. The separator on the terminal is not a space. It is one or more spaces. So if you type into our little ARG printer, one, space, two, space, space, three, space, space, space, four, space, space, space, space, space, five, and then you look at the output, you will see that all of those leading and trailing spaces are gone. Okay, why is that? Because that is how the terminal works. The rule is not break on space. It's break on one or more spaces. So the actual separator is one or more. So 10 spaces counts as one separator. So by just its existence, processing ARGs trims things, right? It trims leading and trailing space. So that's a very useful side effect. If you're going to run stuff through XRX, it will trim your various arguments. Now, why is the XRX- Okay, let me try saying this again. So XRX is going to work on one or more spaces. Yeah. So no matter how many spaces you put in there, it's going to break out as though that was, it just says that whole chunk, it's just gone. The whole chunk is gone. So like when you separate on commas, the commas gone from your output. When you separate on one or more spaces, all the spaces are gone. Okay, that's kind of cool. It is kind of cool. And that's why you will see XRX used just to trim things because it just does it out of the box. But now hang on a sec, Bart. You've done something else here. You've used XRX with zero arguments. There's no command. It's just XRX. The first argument should be the command. Well, when you read the man page, if you don't give XRX a command, it assumes you meant echo. So in other words- That's right, that's right. It'll just print it out to standard out. So it will take whatever you gave it, remove all the spaces you didn't want, and then put it to standard out. That's handy. So we have a whole bunch of leading spaces we don't want. So if you just echo space, space, space for space, space, space, and pipe it to XRX, it will come a perfect four with no leading or trading spaces. So our WC minus C just pipe it to XRX, and all of that glop is gone. And at the end of it all, $PLN has exactly the value we want of two. Because three times 14 is 42, which when counted is two characters and it just comes out two. That's it. Interesting. That is it. So the two most common reasons to use XRX are to take standard in and make it be arguments or to just trim standard in. Just get the leading and trailing glop off it and just give me the nice simple bare value. So even if you never use XRX for the other cool stuff it can do, that's a pretty useful trick right there. It really is. And a lot of the times when I see XRX in Stack Overflow, it's at the very end of a pipeline, just to clean up. It's just sitting there at the end. And whatever else you got left, just clean it up. Yeah, just clean it up. Yeah. So pipe to XRX is very often the last thing in a pipeline. So that is XRX. So let me ask you a question. How much of this did you know before you taught it? I knew that it did what it does, but not enough to explain it. But that was a softball question because Bart sent me a note. He said, I was going to hand wavy over part of this and just really hope you didn't ask the wrong question. I would have suggested that I didn't ask the right question. Agreed. You know the way we talk about bad smells in software engineering? There's a bad smell in show note writing. When I find myself going, I hope Allison doesn't say, Bart, what if the file name has spaces? Because the first version of these show notes, I didn't answer that question because I wasn't sure, but I knew that it was messy. And I knew that the easy answer didn't work on a Mac. What I didn't know was what the best answer for the Mac was. I just knew that the internet was full of people saying things. And people saying things is sometimes right. So I spent this morning with a large cup of coffee and I now understand. So did it tickle your brain going, I really want to know how that works? Yes, it did. Of course it did. And so now I'm going to be better at writing scripts that work everywhere because at the moment I'd sort of been getting by with the fact that with my work hat on, I'm a Red Hat Linux person. So the fact that it only works in new XRs didn't bother me very much, but I'm just going to start doing things across platform way now so that my scripts are much more universal. I like it, I like it. Now the one trick I've learned from Tom Merritt when he does Know a Little More, he talks about, he's teaching something pretty complicated usually and he's trying to boil it down. And he always starts with, so if you really understand this topic, you will know that I am oversimplifying this and I don't want to hear, well actually. So I used it this week when I did a, I did a, I will be publishing a thing about how to use voiceover to test applications on the Mac. And the first thing I say is, so if you really know how to use voiceover, I understand that I am oversimplifying this and I don't want to hear, well actually. You should tell me if I was wrong, but don't tell me that I forgot something, that I skipped something. There's something not in here because I realize that. And I also have a section where I go, so I don't really know whether you're supposed to do A or B and I just bang away at both of them until one of them works and I suspect that there's a better way to do that. That was like hand waving part. That sounds familiar. But no, there is a difference between incomplete and wrong. You can be correct, but incomplete. And if you're explaining things, that's actually often the right thing to do. Don't, I go out of my way not to be wrong, but I also go out of my way to be incomplete because otherwise everyone's head will explode and we will achieve nothing. I will just have recreated the man page with all of the simplicity that goes with the man page. Right, well, like you could have told us all the different ways to deal with these spaces, but giving us two really good ways is a lot more useful than telling us everything. Yeah, yeah, exactly. And I just have this image of my head remembering showing us of how cranky will this make Alison if I go into this detail. Right as you were saying that, I was thinking, oh my gosh, I can't imagine how cranky I would have been last time if you had tried to explain this in the middle of that. Yeah, to be honest, if you had said, how do spaces work, I would have said, I'll get back to you next week. I wouldn't have tried to handle it, but I would have just said, I'll get back to you on that because I have learned. And that's something I learned in my work hat on, right? If you don't know something, the right thing to do is to say you don't know it yet. And there's no shame in saying I don't know that yet. It's different to say to your boss, I don't know and I don't know how to find out. That's not a good answer. I don't know, I'll get back to you, is a really good answer. And it doesn't lose your respect with people. It gains your respect with people because then when you do say something, they'll believe you. Because they know that if you don't know, you won't spoofle. I think you know it, yeah. Yeah, you won't spoofle. You're right, right. I used to say the same thing about salespeople in the technical field where my favorite salespeople for selling me a software product or a hardware product would be somebody who knew everything, knew the answer to all of my technical questions. But my second favorite were the ones where I don't know I'm going to ask somebody smarter than me and I would get back to you. Yeah. That was always better than the ones because there was the third category where they were just making things up and it's not really what you want. Yeah, I don't like being on sales calls with salespeople. I want to be in sales call with the technical people. And you know you are when they say things like... How about those first technical marketing? Yeah, and sometimes that means two humans. They're sometimes okay. Yeah, sometimes that means two humans because they at least keep each other in check. But it's always good when they say things like, yeah, this is not as good as it could be. Then my brain goes, okay, I can believe the rest of this presentation because they are aware of the failures of this product. And then it's much easier to make a case. Anyway, I feel we may be going slightly off topic, but anyway, still interesting I suppose. But I still enjoyed it. And you already gave a plug for podfeed.com slash slack, the PBS channel, lots of fun over there. And I want to give a shout out to Ed Howland who is going through and taking all of Bart's examples and making sure those are published in the student group that we have created on GitHub. If you don't know what that is, send me an email at alisonapodfeed.com and we'll loop you in where you can play along with everybody else seeing everybody's homework on GitHub. And speaking of homework, just a reminder that you do have a challenge from last time and I can now expand the challenge a little. So the challenge is last time I had said to rewrite your solution for the multiplication table to use bash arithmetic instead of the BC command. Well, now I'm going to tell you are there places where XARGs could simplify your code, maybe take two or three lines of code and collapse them into one where you might have had to use variables and there you can just do it all as one pipeline. So try make your code nicer with both arithmetic and XARGs. I do like that I got to a certain point in my homework and I stopped because I got to the point where the example I had to follow had XARGs in it and I said, I don't know what that is. So I waited. So this will be fun. That's a fun little challenge. I like it. Excellent. Okay. Well, until next time, whenever that shall be. Remember folks, happy computing. If you learn as much from Bard each week as I do, I'd like you to go over to let's-talk.ie 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-talk.ie, you can support him on Patreon. You can 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 Podfeet or check out all of the shows we do over there over at podfeet.com. Thanks for listening and stay subscribed.