5

Possible Duplicate:
Vim :s replace first N < g occurrences on a line

In vi, how do I search and replace a word's first n occurrences with a word, say "hello", and the next m occurrences with bonjour, and all the rest with namaste?

varchar1
  • 71
  • 1
  • 5
  • Just a note: the linked question restricts the occurrences to a single line whereas this question seems to be asking about the whole file. However the same techniques would apply by simply prepending a range of `%` to any `:s` command in any of the answers there. – jw013 Jan 24 '12 at 16:24

3 Answers3

0

Can you locate the nth "hello" manually? If so, then, I would locate the nth hello as follows:

:1 (goes to the first line of your file)
n/hello (find the nth hello, where n is the number)

Then substitute all the hellos as follows:

:1,.s/hello/bonjour/g
(move to the next line)
:.,$s/hello/namaste/g
Stephen Quan
  • 511
  • 3
  • 7
  • @Kevin thanks. I was thinking one thing and typed another. I've corrected my answer replacing `.` with `n`. – Stephen Quan Feb 14 '12 at 02:11
  • Yep, that'll work. Not to nag, but `/` [and `n` for that matter] takes an argument, so `5/hello` will find the fifth occurrence of `hello`. – Kevin Feb 14 '12 at 02:16
  • @Kevin thanks, yeah, you're right. You beat me to it as I was just looking that up. – Stephen Quan Feb 14 '12 at 02:19
  • How does one "move to the next line" in vi? I cannot seem to figure that part out. – Chris Boone Jun 19 '20 at 21:46
  • @ChrisBoone there are several ways to move to the next line in `vi`: (1) press `Enter` or `Return`, (2) press `Down Arrow` or `j` key. – Stephen Quan Jun 21 '20 at 22:50
  • @StephenQuan Perhaps I am in an older version of `vi`, but pressing `Enter` or `Return` just sends the command I am entering. I will try the other method. Thank you. – Chris Boone Jun 23 '20 at 12:07
0

This basically boils down to the same as my question (linked in the comments; as mentioned, mine asks about a single line but is trivially generalized to more). The easiest answer is :%s/hello/first/gc, hit y n times and then q, :%s/hello/second/gc, y m times and q, etc. If you need more than a few, use feedkeys and repeat as outlined in the accepted answer there.

Kevin
  • 40,087
  • 16
  • 88
  • 112
0
fun! FUN(n, m)
    if !exists('g:count')
        let g:count = 0
    endif

    let g:count+=1

    if g:count<=a:n
        return 'hello'
    elseif g:count<=a:n+a:m
        return 'bonjour'
    else
        return 'namaste'
    endif
endfun

:unlet! g:count
:%s/word/\=FUN(2, 3)/g

before

word
word
word
word
word
word
word

after

hello
hello
bonjour
bonjour
bonjour
namaste
namaste
kev
  • 941
  • 1
  • 6
  • 13