I'm learning vim script here.
but, I have reached a deadlock.
:let save_ic = &ic
:set noic
:/The Start/,$delete
:let &ic = save_ic
I don't know what $delete means.
Is this an option?
Please tell me what it is.
And, please inform the document related to it.
The interesting line
:/The Start/,$delete
means issuing a command :delete to a range of lines, similar to what :1,10deletewould do. In this case, the first line in the range is the next line where pattern /The Start/ matches, and the last line in range is the last line in the file, $.
For clarity, you can write the command with a space between $ and the command :delete.
You can read through :h rangeto see other options. Here is another presentation of command ranges: The Vim Ranger.
Related
With Vim, if I want to delete every line which has the text pending I can do:
:g/pending/d
How do I do this with a range? Say I want to delete every line with the text pending but only between lines 0 and 60 (or, between 0 and here) something like:
:0,./pending/d
I have searched, but I'm failing to see how to do this. I know you can do
:0,. normal <command> but I'm not sure what the normal mode command to conditionally delete a line is.
p.s. and where do you go in help to learn these things ;)
Like most if not all Ex commands, :global takes a range. So if :g/pending/d does what you want on the whole buffer it will also do what you want on the given range:
:1,.g/pending/d
As for where to find out about this, well… look no further than Vim's documentation.
:help :global says:
*:g* *:global* *E147* *E148*
:[range]g[lobal]/{pattern}/[cmd]
Execute the Ex command [cmd] (default ":p") on the
lines within [range] where {pattern} matches.
Which is pretty clear.
NOTE: lines start at 1.
I'd like to replace current string line with another (for example the another line is placed in 5 lines above current line). I can do it with a pair of commands
dd
:-5t-1
Is there the shorter way to obtain same goal?
dd
:-5t-1
is already pretty short if you ask me. But you can squeeze everything into a one-liner:
:d|-5t-1
and remove the 1 because it's implied by -:
:d|-5t-
Barring making a custom command or mapping I don't see how you could make it shorter.
:-5y<CR>Vp
is it shorter?
if you need do that really often, add this into your vimrc:
command! -range R d|<line1>,<line2>t-
then you can just do :-5R replace current line with -5 line
or 2,4R to cp line 2-4 (3 lines) to current line, and replace current line.
If you don't mind a plugin, my LineJuggler plugin offers a ]r command (and many more):
]r Fetch the line [count] visible lines above the current line and replace the current line with it.
With it, your example would be the short and easy 5]r
In addition, the companion LineJugglerCommands plugin now offers a similar :Replace Ex command. Again, your example would be
:Replace -5
I'm reviewing some logs with Java exception spam. The spam is getting is making it hard to see the other errors.
Is is possible in vim to select a block of text, using visual mode. Delete that block every place it occurs in the file.
If vim can't do it, I know silly question, vim can do everything. What other Unix tools might do it?
Sounds like you are looking for the :global command
:g/pattern/d
The :global command takes the form :g/{pat}/{cmd}. Read it as: run command, {cmd}, on every line matching pattern, {pat}.
You can even supply a range to the :delete (:d for short) command. examples:
:,+3d
:,/end_pattern/d
Put this togehter with the :global command and you can accomplish a bunch. e.g. :g/pat/,/end_pat/d
For more help see:
:h :g
:h :d
:h :range
Vim
To delete all matching lines:
:g/regex/d
To only delete the matches themselves:
:%s/regex//g
In either case, you can copy the visual selection to the command line by yanking it and then inserting it with <C-r>". For example, if your cursor (|) is positioned as follows:
hello wo|rld
Then you can select world with viw, yank the selection with y, and then :g/<C-r>"/d.
sed
To delete all matching lines:
$ sed '/regex/d' file
To only delete the matches themselves:
$ sed 's/regex//g' file
grep
To delete all matching lines:
$ grep -v 'regex' file
grep only operates line-wise, so it's not possible to only delete matches within lines.
you can try this in vim
:g/yourText/ d
Based on our discussion in the comments, I guess a "block" means several complete lines. If the first and last lines are distinctive, then the method you gave in the comments should work. (By "distinctive" I mean that there is no danger that these lines occur anywhere else in your log file.)
For simplifications, I would use "ay$ to yank the first line into register a and "by$ to yank the last line into register b instead of using Visual mode. (I was going to suggest "ayy and "byy, but that wold capture the newlines)
To be on the safe side, I would anchor the patterns: /^{text}$/ just in case the log file contains a line like "Note that {text} marks the start of the Java exception." On the command line, I would use <C-R>a and <C-R>b to paste in the contents of the two registers, as you suggested.
:g/^<C-R>a$/,/^<C-R>b$/d
What if the yanked text includes characters with special meaning for search patterns? To be on the really safe side, I would use the \V (very non-magic) modifier and escape any slashes and backslashes:
:g/\V\^<C-R>=escape(#a, '/\')<CR>\$/,/\V\^<C-R>=escape(#b, '/\')<CR>\$/d
Note that <C-R>= puts you on a fresh command line, and you return to the main one with <CR>.
It is too bad that \V was not available when matchit was written. It has to deal with text from the buffer in a search pattern, much like this.
How to delete all but the first instance of a line, which is known?
For instance, I have
LOADING CONDITION : LIGHTSHIP CONDITION
several of these spread out through the file's contents. I would like to keep only the first instance which is somewhere near the top.
Ideas anyone?
You can use the :global command combined with a range.
:0/LOADING CONDITION/+,$g//d
Explanation:
[range]g/{pat}/{cmd} run a command, {cmd}, on every line matching {pat} inside the giving line range, [range].
0/LOADING CONDITION/ starting with the first line find the pattern LOADING CONDITION
0/LOADING CONDITION/+1 start the range 1 line below the first instance
+1 can be shorted to just + because the 1 can be assumed.
,$ the end of the range will be the last line in the file which is refereed to as $
g// use the last search pattern. In this case the pattern from the range
:delete or :d for short is the ex command used to delete the lines
For more information see
:h :g
:h :d
:h range
gg (make cursor back to top)
/LOADING CONDITION : LIGHTSHIP CONDITION (enter)
n
:.,$g//d
My PatternsOnText plugin provides a command (and other related ones) that makes this very simple:
:DeleteDuplicateLinesOf /^LOADING CONDITION : LIGHTSHIP CONDITION$/
I want to remove percentage marks from the following lines:
oh_test_() ->
[
%{"fold", ?_test(fold(ns()))},
%{"fold nested", ?_test(fold_nested(ns()))},
%{"push arg empty table", ?_test(push_arg_empty_table(ns()))},
%{"push arg table 1", ?_test(push_arg_table1(ns()))},
%{"push arg nested table", ?_test(push_arg_nested_table(ns()))},
%{"multicall 0", ?_test(multicall_0(ns()))},
%{"multicall 1", ?_test(multicall_1(ns()))},
%{"multicall 2", ?_test(multicall_2(ns()))}
].
Cursor is on the line with first %.
:,/%/s/%//
Or:
:,/%/normal ^x
Expected: all percent marks removed. Result: removes only first two percent marks.
Why?
How should I do it
Without using visual mode, and
Not counting line numbers?
Question 1:
Your range: ,/%/ is roughly translated starting from the current line. The end of the range will be the next line that matches /%/ after the current cursor line. This will yield the 2 lines. See :h :, for more information.
Question 2:
There are many ways to do accomplish this. You have already presented a normal and a s/// method. One way to fix your commands is to adjust the range. One of the following will work:
,/\]\./-1 match the ending ]. and then subtract a line
,/^\s*%\(.*\n\s*%\)\#!/ Use a negative look ahead to search for a line that does not start with a %.
All together you could use:
:,/\]\./-1s/%//
:,/^\s*%\(.*\n\s*%\)\#!/s/%//
:,/\]\./-1norm ^x
:,/^\s*%\(.*\n\s*%\)\#!/norm ^x
An alternative to using a macro. The nice thing about using macros in this case is that when an error occurs it stops. Basically you record a macro to search for the % and then delete it then move to the next line. Execute this macro a large number of times. When a % cannot be found the macro will stop.
qq0f%xjq999#q
The macro is my preferred method in this case as I do not need to do any crazy patterns or go looking for the end of the block.
If you allowed the use of visual mode I would suggest vi]k:norm ^x
For more information see:
:h range
:h :,
:h /\#!
:h q
:h #q
:h i]
You first example is basically saying... from my current position until the next % issues the command s/%//...
What you may want to do is something like
:,$ s/%//
which says, for each line from my current position till the end of the file ($), issue the command s/%//
If you didn't want to do it till the end of the file then you could
:set number
Which will show you line numbers, then do something like
:2,8 s/%//
which just issues the command for all lines from 2-8
You seem to be using :,/%/ in a way that should use :g/%/. You could use your command as such: :g/%/s/%// or :g/%/norm f%x
See :help :g for more information on the "global" command. This basically executes a command-mode command on lines matching the pattern. Your version, :,/%/ operates from the current line until the match of "%". This removes the first two because the current line has one and you're searching to the line that has one (the next line). You can read more about this in :help :range. A better way to use this option would be to use a search item that's only on the last line. For example, :,/]/s/%// or :,/]/norm f%x.