2

I need a little help with some vimscript-ing.

I have a huge log file with multiple blocks of text resembling the following:

[log file start]
...
...
Information: Setting NDR rule shield_rule on net a
Information: Setting NDR rule shield_rule on net b
Information: Setting NDR rule shield_rule on net c
Information: Setting NDR rule shield_rule on net d
Information: Setting NDR rule shield_rule on net e
Information: Setting NDR rule shield_rule on net f
Information: Setting NDR rule shield_rule on net g
Information: Setting NDR rule shield_rule on net h
Information: Setting NDR rule shield_rule on net i
Information: Setting NDR rule shield_rule on net j
Information: Setting NDR rule shield_rule on net k
Information: Setting NDR rule shield_rule on net l
Information: Setting NDR rule shield_rule on net m
Information: Setting NDR rule shield_rule on net n
Information: Setting NDR rule shield_rule on net o
Information: Setting NDR rule shield_rule on net p
Information: Setting NDR rule shield_rule on net q
Information: Setting NDR rule shield_rule on net r
...
...
….  <10,000 more lines like above>
….
Information: Updating global clock route.
[log file end]

I would like to write a function bound to ;b that allows me to skip the entire block of similar text. For example, place the cursor at the 1st line of text, hit ;b and have the cursor move to the 1st line immediately after the block of similar text.

I realize I can navigate to the end of the file and search backwards for Information: Setting NDR rule but there may be multiple block occurrences of the text and a backwards search would bring me to the end of the last block.

This is what I have so far:

function! SkipBlockDn()
  let ref = getline(v:lnum)
  execute "normal! j"
  let line = getline(v:lnum)
  "
  "Help needed here to split up the line into words
  "Do a word by word comparison between ref and line
  "If current line and ref match like 80% or so, consider the match close enough and move to next line
  "
  while (line ==# ref)
    execute "normal! j"
    let line = getline(v:lnum)
  endwhile

endfunction
nmap <silent>  ;b  :call SkipBlockDn()<CR>
1
  • 1
    Welcome to Vi and Vim! I've made a few edits to your post. (PS you can write normal! j without execute. You can also use getline('.'). Then there is :help split() or :help =~#.)
    – D. Ben Knoble
    May 12 at 20:57
1

Let me start by offering a solution that you can implement in an ad-hoc fashion, without the need to write Vimscript or pre-define any mappings.

You can use the \@! zero-width negative look-ahead item as part of a pattern to only match lines that do not start with a specific sequence of characters.

In your case, you could use a simple search such as the one below:

/^\(Information: Setting NDR rule shield_rule\)\@!

You can also use the Ctrl+R command from the search input to help you enter the first few words of the current line. (See :help c_CTRL-R.)

For example, you can yank the 6 first words (separated by whitespace) of the current line with 0y6W and then use /^\( followed by Ctrl+R, " to read from the unnamed register, then \)\@! to finish entering the search pattern.

Alternatively, after entering the preamble of /^\(, you can use Ctrl+R, Ctrl+L to insert the line under the cursor, then use Backspace or Ctrl+W to trim the last part of the line you don't want in the match, and finally close the pattern with \)\@! and execute the search.

Of course, you can automate that into a Vimscript function and add a mapping for it. If I were to do so, I'd build a pattern such as the one I described, then use call search() to execute the search with this pattern. The tricky part in writing a function and creating a mapping is probably covering the corner cases (empty lines, lines that are too short, search metacharacters, customize percentage of the line to use, etc.) When using an ad-hoc procedure, it's usually easy to spot those issues and adapt the search to cope with them.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.