Skip to content

Commit 4d0a29f

Browse files
author
iggy
committed
add ze, zs, and non-greedy examples
1 parent d766aa4 commit 4d0a29f

1 file changed

Lines changed: 124 additions & 4 deletions

File tree

ch12_search_and_substitute.md

Lines changed: 124 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,36 @@ To match both "hello" and "hola", you can do `/hello\|hola`. You have to escape
7878

7979
If you don't want to type `\|` every time, you can use the `magic` syntax (`\v`) at the start of the search: `/\vhello|hola`. I will not cover `magic` in this chapter, but with `\v`, you don't have to escape special characters anymore. To learn more about `\v`, feel free to check out `:h \v`.
8080

81+
# Setting the Start and End of a Match
82+
83+
Maybe you need to search for a text that is a part of a compound word. If you have these texts:
84+
85+
```
86+
11vim22
87+
vim22
88+
11vim
89+
vim
90+
```
91+
92+
If you need to select "vim" but only when it starts with "11" and ends with "22", you can use `\zs` (starting match) and `\ze` (ending match) operators. Run:
93+
94+
```
95+
/11\zsvim\ze22
96+
```
97+
98+
Vim still has to match the entire pattern "11vim22", but only highlights the pattern sandwiched between `\zs` and `\ze`. Another example:
99+
100+
```
101+
foobar
102+
foobaz
103+
```
104+
105+
If you need to search for the "foo" in "foobaz" but not in "foobar", run:
106+
107+
```
108+
/foo\zebaz
109+
```
110+
81111
# Searching Character Ranges
82112

83113
All your search terms up to this point have been a literal word search. In real life, you may have to use a general pattern to find your text. The most basic pattern is the character range, `[ ]`.
@@ -232,7 +262,7 @@ In Vim, `%` usually means the entire file. If you run `:%s/let/const/`, it will
232262

233263
# Pattern Matching
234264

235-
The next few sections will cover basic regular expressions. A strong pattern knowledge is essential to master the substitute command.
265+
The next few sections will cover basic regular expressions. A strong pattern knowledge is essential to master the substitute command.
236266

237267
If you have the following expressions:
238268

@@ -495,16 +525,106 @@ Here is the breakdown:
495525
- `\1` is the first match group, which is either the text "hello" or "hola".
496526
- `friend` is the literal word "friend".
497527

528+
# Substituting the Start and the End of a Pattern
529+
530+
Recall that you can use `\zs` and `\ze` to define the start and the end of a match. This technique works in substitution too. If you have:
531+
532+
```
533+
chocolate pancake
534+
strawberry sweetcake
535+
blueberry hotcake
536+
```
537+
538+
To substitute the "cake" in "hotcake" with "dog" to get a "hotdog":
539+
540+
```
541+
:%s/hot\zscake/dog/g
542+
```
543+
544+
Result:
545+
546+
```
547+
chocolate pancake
548+
strawberry sweetcake
549+
blueberry hotdog
550+
```
551+
552+
You can also substitute the nth match in a line with this trick:
553+
554+
```
555+
One Mississippi, two Mississippi, three Mississippi, four Mississippi, five Mississippi.
556+
```
557+
558+
To substitute the third "Mississippi" with "Arkansas", run:
559+
560+
```
561+
:s/\v(.{-}\zsMississippi){3}/Arkansas/g
562+
```
563+
564+
The breakdown:
565+
- `:s/` the substitute command.
566+
- `\v` is the magic keyword so you don't have to escape special keywords.
567+
- `.` matches any single character
568+
- `{-}` performs non-greedy match of 0 or more of the preceding atom.
569+
- `\zsMississippi` makes "Mississippi" the start of the match.
570+
- `(...){3}` looks for the third match.
571+
572+
You have seen the `{3}` syntax before. It is a type of `{n,m}`. In this case, you have `{3}` which will match exactly the third match. The new trick here is `{-}`. It is a non-greedy match. It finds the shortest match of the given pattern. In this case, `(.{-}Mississippi)` matches the least amount of "Mississippi" preceded by any character. Contrast this with `(.*Mississippi)` where it finds the longest match of the given pattern.
573+
574+
If you use `(.{-}Mississippi)`, you get five matches: "One Mississippi", "Two Mississippi", etc. If you use `(.*Mississippi)`, you get one match: the last "Mississippi". To learn more check out `:h /\{-` and `:h non-greedy`.
575+
576+
Let's do a simpler example. If you have the string:
577+
578+
```
579+
abc1de1
580+
```
581+
582+
You can match "abc1de1" (greedy) with:
583+
584+
```
585+
/a.*1
586+
```
587+
588+
You can match "abc1" (non-greedy) with:
589+
590+
```
591+
/a.\{-}1
592+
```
593+
594+
So if you need to uppercase the longest match (greedy), run:
595+
596+
```
597+
:s/a.*1/\U&/g
598+
```
599+
600+
To get:
601+
602+
```
603+
ABC1DEFG1
604+
```
605+
606+
If you need to uppercase the shortest match (non-greedy), run:
607+
608+
```
609+
:s/a.\{-}1/\U&/g
610+
```
611+
612+
To get:
613+
614+
```
615+
ABC1defg1
616+
```
617+
498618
# Substituting Across Multiple Files
499619

500620
Finally, let's learn how to substitute phrases across multiple files. For this section, assume that you have two files: `food.txt` and `animal.txt`.
501621

502622
Inside `food.txt`:
503623

504624
```
505-
corn dog
506-
hot dog
507-
chili dog
625+
corndog
626+
hotdog
627+
chilidog
508628
```
509629

510630
Inside `animal.txt`:

0 commit comments

Comments
 (0)