What Does Pipe Character Do in Vim Command Mode? (For Example,: Vimgrep /Pattern/ File | Another_Cmd)

What does pipe character do in vim command mode? (for example, :vimgrep /pattern/ file | another_cmd)

| is used to execute more than one command at a time.

In your example:

:vimgrep /pattern/ file | copen

This finds for the pattern in the specified file and then opens a window to show current list of occurrence of pattern.

The second command (and subsequent commands) are only executed if the prior command succeeds.

vim - navigating characters in command mode

For small edits, Backspace and light use of the cursor keys should be fine. For anything larger, I would advise to use the command-line window:

In the command-line window the command line can be edited just like editing
text in any window.

So, there's no need to mentally switch to readline key mappings; just use the full editing power (including any custom mappings) of Vim!

You can switch via <C-F> from the command-line, or directly enter it (from normal mode) by pressing q: instead of :. All the details can be found at :help cmdline-window.

VIM - Hotkey for VIMGREP on Visual Selection in current buffer

A low-level solution

Try [I and the :ilist command:

[I                 " lists every occurrence of the word under the cursor
" in the current buffer (and includes)

:ilist /foo<CR> " lists every occurrence of foo in the current buffer
" (and includes)

Press : followed by a line number and <CR> to jump to that line.

You can use them on the visual selection with a simple mapping:

xnoremap <key> "vy:<C-u>ilist /<C-r>v<CR>:

You'll probably need to sanitize the register upon insertion, though.

See :help :ilist.

Another even lower-level solution

Since we are at it, let's dig even deeper and find the amazingly simple and elegant:

:g/foo/#

that you could use in the same way as :ilist above:

xnoremap <key> "vy:<C-u>g/<C-r>v/#<CR>:

Limitations

The solutions above don't use the quickfix window, obviously, but they allow you to:

  • see their result as a list,
  • use line numbers to actually get to where you want.

They have limitations, though:

  • the list is not cached so you must perform the search again if you want to get to a different occurrence,
  • the list is not transient like the quickfix list so you can't use navigation commands like :cnext or :clast to move around the result.

A higher-level solution

If those limitations are a showstopper, the function below, adapted from justinmk's answer in this /r/vim thread, gives you an almost complete solution:

  • press [I in normal mode to search for the word under the cursor in the whole buffer,
  • press ]I in normal mode to search for the word under the cursor after the current line,
  • press [I in visual mode to search for the selected text in the whole buffer,
  • press ]I in visual mode to search for the selected text after the current line.

The function below uses the quickfix list/window when the buffer is associated to a file and falls back to the regular behavior of [I and ]I otherwise. It could probably be modified to be used as part of an :Ilist command.

" Show ]I and [I results in the quickfix window.
" See :help include-search.
function! Ilist_qf(selection, start_at_cursor)

" there's a file associated with this buffer
if len(expand('%')) > 0

" we are working with visually selected text
if a:selection

" we build a clean search pattern from the visual selection
let old_reg = @v
normal! gv"vy
let search_pattern = substitute(escape(@v, '\/.*$^~[]'), '\\n', '\\n', 'g')
let @v = old_reg

" and we redirect the output of our command for later use
redir => output
silent! execute (a:start_at_cursor ? '+,$' : '') . 'ilist /' . search_pattern
redir END

" we are working with the word under the cursor
else

" we redirect the output of our command for later use
redir => output
silent! execute 'normal! ' . (a:start_at_cursor ? ']' : '[') . "I"
redir END
endif
let lines = split(output, '\n')

" better safe than sorry
if lines[0] =~ '^Error detected'
echomsg 'Could not find "' . (a:selection ? search_pattern : expand("<cword>")) . '".'
return
endif

" we retrieve the filename
let [filename, line_info] = [lines[0], lines[1:-1]]

" we turn the :ilist output into a quickfix dictionary
let qf_entries = map(line_info, "{
\ 'filename': filename,
\ 'lnum': split(v:val)[1],
\ 'text': getline(split(v:val)[1])
\ }")
call setqflist(qf_entries)

" and we finally open the quickfix window if there's something to show
cwindow

" there's no file associated with this buffer
else

" we are working with visually selected text
if a:selection

" we build a clean search pattern from the visual selection
let old_reg = @v
normal! gv"vy
let search_pattern = substitute(escape(@v, '\/.*$^~[]'), '\\n', '\\n', 'g')
let @v = old_reg

" and we try to perform the search
try
execute (a:start_at_cursor ? '+,$' : '') . 'ilist /' . search_pattern . '<CR>:'
catch
echomsg 'Could not find "' . search_pattern . '".'
return
endtry

" we are working with the word under the cursor
else

" we try to perform the search
try
execute 'normal! ' . (a:start_at_cursor ? ']' : '[') . "I"
catch
echomsg 'Could not find "' . expand("<cword>") . '".'
return
endtry
endif
endif
endfunction

nnoremap <silent> [I :call Ilist_qf(0, 0)<CR>
nnoremap <silent> ]I :call Ilist_qf(0, 1)<CR>
xnoremap <silent> [I :<C-u>call Ilist_qf(1, 0)<CR>
xnoremap <silent> ]I :<C-u>call Ilist_qf(1, 1)<CR>

NB: <C-r><C-w> inserts the word under the cursor, not the visual selection for which there's unfortunately no such shortcut. We have no choice but to yank.

How to use regex in vim to replace with an incrementing number variable

Mind that you can use an expression as the replacement string in the substitute command (:s). When the replacement string starts with \= it is evaluated as an expression.

Here, one possible solution is

:let i=1 | g/^x'\d\+'/s//\=i/ | let i=i+1

It finds all occurrences (one per line) of the ^x'\d\+' pattern and replaces it with the value if i that is incremented each time the match is found. As has been noted in comments, the | is a part of the g replacing "code", as "| is used to execute more than one command at a time".

Another solution is using the line() command (taking into account that your file has a header top line, so you should actually subtract 1 from the value returned with line()):

%s/^x'\d\+'/\=line('.')-1/

The ^x'\d\+' regex matches

  • ^ - start of a line
  • x' - x' string
  • \d\+ - 1+ digits
  • ' - a ' char.

There are other interesting "increment number in regex" examples at the Using an expression in substitute command page:

  • Number all the lines in a file (insert line number followed by a tab):

    :%s/^/\=line('.')."\t"/
  • Number a range of lines (from line 10 to line 20):

    :10,20s/^/\=line('.')."\t"/
  • Number a range of lines sequentially starting from 1:

    :let counter=0|10,20g//let counter=counter+1|s/^/\=counter."\t"
  • Number all the paragraphs in range starting from 1 (assuming the paragraphs are separated by one or more blank lines):

    :let counter=0|1,20g/^$\n^\s*[^\s]/let counter=counter+1|+1s/^/\=counter."\t"

    Note: The above command does not work for the first paragraph in the file if there is no blank line above it.

Vim Regex Capture Groups [bau - byau : ceu - cyeu]

One way to fix this is by ensuring the pattern is enclosed by escaped parentheses:

:%s/\(\w\)\(\w\w\)/\1y\2/g

Slightly shorter (and more magic-al) is to use \v, meaning that in the pattern after it all ASCII characters except '0'-'9', 'a'-'z', 'A'-'Z' and '_' have a special meaning:

:%s/\v(\w)(\w\w)/\1y\2/g

See:

  • :help \(
  • :help \v

How to replace a character by a newline in Vim

Use \r instead of \n.

Substituting by \n inserts a null character into the text. To get a newline, use \r. When searching for a newline, you’d still use \n, however. This asymmetry is due to the fact that \n and \r do slightly different things:

\n matches an end of line (newline), whereas \r matches a carriage return. On the other hand, in substitutions \n inserts a null character whereas \r inserts a newline (more precisely, it’s treated as the input CR). Here’s a small, non-interactive example to illustrate this, using the Vim command line feature (in other words, you can copy and paste the following into a terminal to run it). xxd shows a hexdump of the resulting file.

echo bar > test
(echo 'Before:'; xxd test) > output.txt
vim test '+s/b/\n/' '+s/a/\r/' +wq
(echo 'After:'; xxd test) >> output.txt
more output.txt
Before:
0000000: 6261 720a bar.
After:
0000000: 000a 720a ..r.

In other words, \n has inserted the byte 0x00 into the text; \r has inserted the byte 0x0a.

How can I search a word in whole project/folder recursively?

:vimgrep /JFactory/ **/*.java

You can replace the pattern /JFactory/ with /\<JFactory\>/ if you want full word match. :vim is shorthand for :vimgrep.

If JFactory or \<JFactory\> is your current search pattern (for example you have hit * on one occurrence) you can use an empty search pattern: :vimgrep // **/*.java, it will use last search pattern instead. Handy!

Warning: :vimgrep will trigger autocmds if enabled. This can slow down the search. If you don't want that you can do:

:noautocmd vimgrep /\<JFactory\>/ **/*.java

which will be quicker. But: it won't trigger syntax highlighting or open gz files ungzipped, etc.

Note that if you want an external program to grep your pattern you can do something like the following:

:set grepprg=ack
:grep --java JFactory

Ack is a Perl-written alternative to grep. Note that then, you will have to switch to Perl regexes.

Once the command of your choice returned, you can browse the search results with those commands described in the Vim documentation at :help quickfix. Lookup :cfirst, :cnext, :cprevious, :cnfile, etc.

2014 update: there are now new ways to do that with the_silver_searcher or the_platinum_searcher and either ag.vim or unite.vim plugins.

Vim regular expression to match string with prefix and suffix

The command below should work unless "any character" means something different for you than for Vim:

:g/abc.*xyz
  • . means "any character except an EOL".
  • * means "any number (including 0) of the previous atom".
  • 1,$ could be shortened to %.
  • :global works on the whole buffer by default so you don't even need the %.
  • The closing / is not needed if you don't follow :g/pattern by a command as in :g/foo/d.


Related Topics



Leave a reply



Submit