Transforming & Substituting Text
The course is part of this learning path
This course covers how to transform and substitute text in Vim. We look at how to insert, replace, change, and join texts through a range of commands, and then you'll have the opportunity to try these out by following along with a guided demo.
Then we move on to searching, finding, and replacing text within files, and once again, they'll be a guided walkthrough to show you the real-world application of these features.
This course is ideal for anyone who needs to edit text files in a command-line environment.
If you want to follow along with the exercises in this course, you should have the Vim text editor installed on your computer.
If you want to follow along with the exercise(s) in this course, you can find the necessary resources here.
As a system admin, I can think of many times where I've had to change every occurrence of a given string in a file to something new. For example, if I've had to copy over a configuration file from one server to another one, I will want to change the server name in that file and it may appear in it multiple places. I've also had to do similar things with shell scripts and Python programs. Luckily, Vim has Find and Replace functionality in the form of the :s, or substitute command. In its simplest form, the substitute command is :s/old/new/. This replaces the text old, with the text new. I'm gonna hit Escape to abandon this command. Let's move down to the line that starts with capital domain. So I can do a forward search to do that, /DOM and press Enter. If you want to change example.net to example.org, you can type :s/net/org/ and press Enter. Notice how the substitution was only performed on the current line, and only changed the first occurrence of net to org on the line. You can see toward the end of the line there's another occurrence of net. An optional part of the substitute command is the flag section. So it looks like this, :s/old/new/[flags]. The most common flag I use is the g flag, which causes the substitute command to replace all occurrences in the line. It doesn't matter if the pattern appears once or 100 times on a line, using the g flag will cause all of them to get replaced. As a matter of fact, using the g flag is almost an automatic habit for me because I typically want to change every occurrence on a line, not just the first one. Anyway, let's do that here. I'll hit Escape to abandon this command, and I'll hit u to undo our substitution command. Now the line is back to how it started. So this time let's use, :s, to substitute, /net/org/g, which is our g flag, and press Enter. Now you can see that net was replaced with org on both places on that line. In addition to being able to supply flags to the substitute command, you can proceed it with a range to operate on. So the pattern of that command is an optional [Range], followed by the S command, /the old pattern, /the new pattern, /[flags] that you want to specify. By the way, the default range is the current line which is why the substitute command operates on the current line only by default. Now a range is one or more line specifier separated by a comma or semi-colon. The simplest range is a line number. Let's abandon this change here. For example, to change the word is to isn't on line one you can run :1, which is the range, s, the substitute command, the old pattern, the new pattern, isn't, and then press Enter. Another example of a range is 1,5 which is the first five lines of the file. So if you wanted to change, let's say the characters f-o-r, from lowercase to uppercase, but only on the first five lines, we can execute this command, :1,5s/for/FOR /g to make sure each occurrence on the line is replaced and then press Enter. You'll see that the word f-o-r on the sixth line of the file was unchanged because we only operated on that range of line one through line five. There are also some special characters that represent lines. For example, the dollar sign represents the last line in the file. Also, a period represents the current line in the file. So you can use a range like period, comma, dollar sign which includes the current line, all the way through the last line in the file. The special character range that I use most often is the percent sign, which is the range for the entire file. You can even think of it as being the same as 1,$. So if you want to change every occurrence of net in the file to org, what we can do is :%s/net/org/g for our g flag, again, that I use so often and I'm going to press Enter. And here you can see at the bottom it says four substitutions occurred on three different lines. Let's undo that change with u. There's another way to specify a range, and that is by a pattern. You can specify a pattern with forward slashes, so if we only want to change net to org in the section starting with # Global configuration and ending with # Local configuration you can use this command, :/Global/ which is one pattern, , the next pattern which is /Local/ then the command which is substitute, which is s/net/org/g for our g flag, and we'll hit Enter. So you'll only see changes that were made on the lines that fall within those search patterns. So again, if you look kinda toward the bottom of the screen, those occurrences of net were not replaced with org because those were not in between our search patterns. Know that you can combine these search patterns with line numbers or special characters, like the dollar sign too, so to change something from local configuration to the end of the file, we can use this :/Local/,$, that means everything from the search pattern that matches local, all the way to, and including, the last line of the file is our range. Now we can use our command here, s/net/org and our flag g, and press Enter. Now you can see that three more substitutions were made on two lines that occurred in between the local and the end of the file. If you happen to work on Linux, Unix, or Mac systems, you might've noticed that the pattern separator we're using in Vim also happens to be the directory separator for those operating systems. It's not uncommon that you'll need to change a path with a substitute command, especially if you're working with configuration files. Now I'm gonna show you the hard way to do this first, but stick with me, I'm gonna show you the easy way after that. I'm just gonna move down to the Mail_Path line, here, with j, and I'm gonna show you the hard way which is to escape each forward slash with a backslash. For example, to replace /var/spool with /user/local, you could use :s/\/var\/spool/\/usr\/local/ and press Enter. That totally works, but it really slows me down because I have to be careful and think closely about what I'm doing. So that's the hard way, that's a lot of thinking. Now the easy way is just to use a different character for the pattern separator, I like to use the pound sign. You can use any other single non alphanumeric character that you like, again, I like the pound sign. Some people like to use the pipe symbol, others like to use a comma, whatever, you can use a plus sign or even an equal sign. So let's undo our chains by typing u first. So now instead of using a forward slash let's use a pound sign like so, so I'll do :s#, being the pattern separator here, and the first pattern I'm looking for, the old pattern is /var/spool, and the new pattern is, I'll separate that with a hash symbol too, is /usr/local, and we'll end our pattern there and press Enter, and we get the same result. I could have made this even a bit simpler by leaving out the leading forward slash because it really wasn't replaced, but I wanted to leave it there just to demonstrate how this method works clearly. Since you were introduced to ranges, and ranges use line numbers, I think now's a good time to show you how to turn on line numbering. And to do that, all's you have to do is type :set nu, short for number, and press Enter. The set command is used to control Vim's options. The n-u option is short for number, so :set nu or :set number turns on line numbering. To turn off line numbering, we can use :set nonu and press Enter, or :set nonumber. This is a pattern by the way, for options that can either be turned on or off, like line numbering, use :set and the option name to turn it on, and :set no, followed by the option name to turn it off. Instead of explicitly turning an option on or off, you can append an exclamation mark to the end of the option to toggle it. So that means you can use :set nu! to toggle line numbering on, and then we can use the same command, again, to toggle it back off. Let's quickly recap this lesson with what you've learned. You started off by learning how to search forward on the same line with the f command. You learned how to search backwards using capital F. Next, you learned the till command using lowercase t to search forward till, and uppercase T to search backwards till. You also learned how to use the semi-colon to repeat your most recent search in the same direction, and how to repeat that search in the opposite direction by using a comma. Then you moved on to searching within the entire file by using forward slash, followed by a search pattern. Next, you learned how to perform a reverse search by using a question mark, followed by a search pattern. You learned how to use lowercase n to repeat your search in the same direction that it was started in, and capital N to repeat your search in the opposite direction. You learned how to search for a word nearest, or under your cursor by using the asterisk to search forward, and the pound sign to search backwards. Next, you learned how to use the substitute command. You also learned about ranges and how you can limit the substitute command to operate only on the range you specify. Most importantly, you learned how to perform a global substitution by using the percent sign as the range, and using the g flag to replace all occurrences within a line. Along the way you were reminded how to repeat commands by using a count before a command. You are also able to combine the new motions you learned with commands you already knew, such as delete, change and yank.
Jason is the founder of the Linux Training Academy as well as the author of "Linux for Beginners" and "Command Line Kung Fu." He has over 20 years of professional Linux experience, having worked for industry leaders such as Hewlett-Packard, Xerox, UPS, FireEye, and Amazon.com. Nothing gives him more satisfaction than knowing he has helped thousands of IT professionals level up their careers through his many books and courses.