How do I delete first word of each line in Vim?
How about a pattern on each line?
:normal to the rescue:
:%norm dw
It basically replays the arguments as if you were typing them in normal ('non-edit') mode.
From :help :
:norm[al][!] {commands}
Execute Normal mode commands {commands}.
This makes it possible to execute Normal mode commands typed on the
command-line. {commands} is executed like it is typed.
Going for cryptic here, in true vi style:
1Gq10dwjq100000#1
Randy fixed this up in the comments to work on more than 100000 lines:
ggqqdwj#qq#q
For those starting out with Vim, this breaks down to:
gg - Go to first line
qq - Record a macro into register 'q'
dwj#q - The macro:
dw - delete word at cursor
j - go down one line
#q - run the macro in register 'q'
q - Stop recording the macro
#q - Execute the macro in register 'q'
In essence, the macro is recursive - it deletes a word, moves down a line, then calls itself again, repeating for each line until end of file. The final '#q' is the initial (manual) call needed to set the macro off on every line.
I would use something like the following:
:%s/^\w+\s+//
The regular expression will match one or more "word" characters starting at the beginning of the line followed by at least one whitespace character. It will remove the word and any following whitespace. If a line can contain only a single word -- and you still want it removed -- you could use alternation to match either whitespace or the end of line.
:%s/^\w+(\s+|$)//
First word (where word is defined as no whitespace)
:%s/^\s*[^ ]* //g
Delete pattern:
:%s/< insert pattern here >//g
What about this?
:%!cut -s -d' ' -f2-
:%s,^[^ ]*,,
From the beginning of the line match anything, but not a space and replace with none.
Although this is an old question, if someone else is looking to do this you could do use visual block.
press ctrl+v
select all the lines you would want to edit
now use arrow keys to select the entire word
press 'x'
That would delete the first word in all the lines. This method is especially very handy to edit log files
Related
I had a large file I was trying to reformat which involved removing the 2nd to nth repeating sets on 2 to 100 lines per duplicate.
The data looked like
element1.element2.element...field.comment
I wanted to remove the repetition in elements after the first instance so of course I went complicated :) and did a macro something like
In a macro Yanked first element on current line to register p and then processed lines yanking the first element into register o and then doing, still in the macro
:if (#p=!#o)|:.s/paste register p//g|else|:norm! j|endif
Now this worked OK except when it got to a line where #p<>#o the :norm! j part stayed in : mode until I manually escaped once or twice then executed the :norm! j command.
I solved the problem an easier way but would like to know why it was only on the else portion that it wouldn't leave :ex mode.
From :help norm
:norm[al][!] {commands} *:norm* *:normal*
...
This command cannot be followed by another command,
since any '|' is considered part of the command.
...
An alternative is to use |:execute|, which uses an
expression as argument. This allows the use of
printable characters to represent special characters.
Example: >
:exe "normal \<c-w>\<c-w>"
So this would do the trick:
:if (#p=!#o)|:.s/paste register p//g|else|:exe "norm j"|endif
Please let me know, How I can remove the last word from each line using vim commands?
Before :
abcdef 123
xyz 1256
qwert 2
asdf 159
after :
abcdef
xyz
qwert
asdf
Similarly please let me know how to remove the second word from each line using vim command?
Use the following regex (in ex mode):
%s/\s*\w\+\s*$//
This tells it to find optional whitespace, followed by one or more word characters, followed by optional whitespace, followed by end of line—then replace it with nothing.
The question's been answered already, but here's what I'd more likely end up doing:
Record a macro:
qq to record a macro into register "q"
$ to go to the end of the line
daw to delete a word
q to stop recording
Then select the rest of the lines:
j to go down a line
vG to select to the end of the file
And apply the macro:
:norm #q
Some similar alternatives:
:%norm $daw
qq$dawjq (note the added j) then 999#q to replay the macro many times. (Macro execution stops at the first "error" -- in this case, you'd probably hit the bottom of the file, j would not work, and the macro would stop.)
The key for this is the :substitute command; it is very powerful (and often used in vi / Vim).
You need to come up with a regular expression pattern that matches what you want to delete. For the last word, that's whitespace (\s), one or more times \+ (or any number (*), depending on how you want to treat single-word lines), followed by word characters (\w\+), anchored to the end of the line ($). Note that word has a special meaning in Vim; you may want to use a different atom (e.g. \S). Voila:
:%s/\s\+\w\+$//
For the second word, you can make use of the special \zs and \ze atoms that assert for matches, but do not actually match: Anchored at the start (^), match a word, then start the match for a second one:
:%s/^\w\+\s\+\zs\w\+\s\+//
Soon, you'll also want to reorder things, not just remove them. For that, you need to know capturing groups: \(...\). The text matched by those can then be referred to in the replacement part. For example, to swap the first and second words:
:%s/^\(\w\+\s\+\)\(\w\+\s\+\)/\2\1/
For details, have a look at the help, especially :help :substitute and :help pattern.
To remove the second word from the start of a line, use the following:
:%s/^\(\s*\w\+\s\+\)\w\+\s*/\1/
Update
To treat special characters as part of the word, you have to use the \S (which matches all non-whitespace characters) instead of \w (which matches only word characters [0-9A-Za-z_]). Then, the command would be:
:%s/^\(\s*\S\+\s\+\)\S\+\s*/\1/
Suppose I'm editing the following document (* = cursor):
Lions
Tigers
Kittens
Puppies
*
Humans
What sequence can I use to delete the surrounding white space so that I'm left with:
Lions
Tigers
Kittens
Puppies
*
Humans
Note: I'm looking for an answer that handles any number of empty lines, not just this exact case.
EDIT 1: Line numbers are unknown and I only want to effect the span my cursor is in.
EDIT 2: Edited example to show I need to preserve leading whitespace on edges
Thanks
Easy. In normal mode, dipO<Esc> should do it.
Explanation:
dip on a blank line deletes it and all adjacent blank lines.
O<Esc> opens a new empty line, then goes back to normal mode.
Even more concise, cip<Esc> would roll these two steps into one, as suggested by #Lorkenpeist.
A possible solution is to use the :join command with a range:
:?.?+1,/./-1join!
Explanation:
[range]join! will join together a [range] of lines. The ! means with out inserting any extra space.
The starting point is to search backwards to the first character then down 1 line, ?.?+1
As the 1 in +1 can be assumed this can be abbreviated ?.?+
The ending point is to search forwards to the next character then up 1 line, /./-1
Same as before the 1 can be assumed so, /./-
As we are using the same pattern only searching forward the pattern can be omitted. //-
The command :join can be shorted to just :j
Final shortened command:
:?.?+,//-j!
Here are some related commands that might be handy:
1) to delete all empty lines:
:g/^$/d
:v/./d
2) Squeeze all empty lines into just 1 empty line:
:v/./,//-j
For more help see:
:h :j
:h [range]
:h :g
:h :v
Short Answer: ()V)kc<esc>
In normal mode, if you type () your cursor will move to the first blank line. ( moves the cursor to the beginning of the previous block of non-blank lines, and ) moves the cursor to the end (specifically, to the first blank line after said block). Then a simple d) will delete all text until the beginning of the next non-blank line. So the complete sequence is ()d).
EDIT: You're right, that deletes the whitespace at the beginning of the next non-blank line. Instead of d) try V)kd. V puts you in visual line mode, ) jumps to the first non-blank line (skipping the whitespace at the beginning of the line), k moves the cursor up one line. At this point you've selected all the blank lines, so d deletes the selection.
Finally, type O (capital O) followed by escape to crate a new blank line to replace the ones you deleted. Alternatively, replacing dO<Escape> with c<Escape> does the same thing with one less keystroke, so the entire sequence would be ()V)kc<Esc>.
These answers are irrelevant after the updated question:
This may not be the answer you want to hear, but I would make use of ranges. Take a look at the line number for the first empty line (let's say 55 for example) and the second to last empty line (perhaps 67). Then just do :55,67d.
Or, perhaps you only want there to ever be one empty line in your whole file. In that case you can match any occurrence of one or more empty lines and replace them with one empty line.
:%s/\(^$\n\)\+/\r/
This answer works:
If you just want to use normal mode you could search for the last line with something on it. For instance,
/.<Enter>kkVNjd
I didn't test so much, but it should work for your examples. There maybe more elegant solutions.
function! DelWrapLines()
while match(getline('.'),'^\s*$')>=0
exe 'normal kJ'
endwhile
exe 'silent +|+,/./-1d|noh'
exe 'normal k'
endfunction
source it and try :call DelWrapLines()
I know this question has already been resolved, but I just found a great solution in "sed & awk, 2nd Ed." (O'Reilly) that I thought was worth sharing. It does not use vim at all, but instead uses sed. This script will replace all instances of one or more blank lines (assuming there is no whitespace in those lines) with a single blank line. On the command line:
sed '/ˆ$/{
N
/ˆ\n$/D
}' myfile
Keep in mind that sed does not actually edit the file, but instead prints the edited lines to standard output. You can redirect this input to a file:
sed '/ˆ$/{
N
/ˆ\n$/D
}' myfile > tempfile
Be careful though, if you try to write it directly to myfile, it will just delete the entire contents of the file, which is clearly not what you want! After you write the output to tempfile, you can just mv tempfile myfile and tada! All instances of multiple blank lines are replaced by a single blank line.
Even better:
cat -s myfile > temp
mv temp myfile
cat is awesome, yes?
Bestest:
If you want to do it inside vim, you can replace all instances of multiple blank lines with a single blank line by using vim's handy feature of executing shell commands on a range of lines within vim.
:%!cat -s
That's all it takes, and your entire file is reformatted all nice!
I have the following Ruby code:
if some_cond && another
foo_bar
end
and I want to change it to:
foo_bar if some_cond && another
What are the most idiomatic ways to do that in Vim?
Assuming that the cursor is located at the if-line prior to
refactoring (not necessarily at the beginning of that line),
I would use the following sequence of Normal-mode commands:
ddjVpkJ<<
or this chain of Ex commands:
:m+|-j|<|+d
Here the if-line is first moved down one line by the :move + command.
The :move command cuts a given range of lines (the current line, if
not specified) and pastes it below the line addressed by the argument.
The + address is a shorthand for .+1 referring to the next line
(see :help {address}).
Second, the line containing the body of the conditional statement is
joined with the just moved if-line. The :join command concatenates
a given range of lines into a single line. The - range is a shortened
form of the .-1 address referring to the line just above the cursor
(see :help {address}).
Third, the newly joined line is unindented by one shiftwidth using
the :< command.
Finally, the remaining end-line, which can now be addressed as +,
is removed by the :delete command.
I see few (probably non-optimal) solutions:
cursor in first character in first line:
D - remove if condition but leave cursor in same position (don't delete line)
J - join next line to current
A <Space> <ESC> - append space and exit to Normal mode
p - paste if condition
and then remove remaining end with jdd
cursor in first character in first line, as previously:
j - move to next line
dd - remove this line
k - move back to if condition
P - paste removed line before actual line, cursor should be placed to pasted line
J - join next line to current
== or << - unindent current line
and then remove remaining end with jdd
another solution:
j - move to second line
JD - join line with next, remove what was joined
dd - remove current line
k - step to previous line
PJ<< - paste, join and unshift
It's probably not optimal, but I do it without thinking, because most of this commands are in my muscle memory (you don't think how to move around you, how to yank/delete and paste most of the time, and joining line is also helpful to remember).
If you have virtualedit enabled in config, instead of A <Space> <Esc> you can $ <Space>, but I find $ harder to use than A followed by Ctrl-[ (it's simmilar to ESC).
As an advice: if you use some upper letter commands, try to chain them if it's possible, so you only need to keep Shift pressed and then execute some commands, instead of mixing upper and lower letter commands and pressing two keys at a time (upper letter is 2 key press, one is Shift). Once I found combo helpful for restarting server in console Ctrl+cpj, which sends Ctrl+c, Ctrl+p (previous command) and Ctrl+j (Enter key) with single Ctrl press. Since then I try to find simmilar time-saving combination in Vim too mostly with Shift, as Ctrl is not much used in Vim.
Yet another way:
ddpkJjdd
ddp swap the two lines
kJ move up and join the lines
== re-indent the line
jdd move down and delete the last line
There are probably 30 ways to do this.
Here is one, assuming you are starting from the end of the word end in normal mode:
dd (delete last line)
"aD (delete and copy foo_bar to buffer a)
dd (delete now-empty line 2)
"aP (paste from buffer a before caret)
aSpaceEsc (insert space and return to normal mode)
Again, "properly" rarely applies in Vim because there are so many ways to accomplish something. This is so small a change that even re-typing foo_bar could be justifiable.
Say I have ten lines and I want to prepend text to some word that occurs in those lines? It does not have to be at the beginning of the line.
From:
sdfsd foo sdfsd
sfsd foo fsdf
sdfsdf foo sdfsdf
to:
sdfsd bar(foo sdfsd
sfsd bar(foo fsdf
sdfsdf bar(foo sdfsdf
Is it also possible to not only prepend the bar( but actually surround foo with bar(foo)?
I would also like a quick way to append // comments to multiple lines (C-style comments).
I use Vim/GVim 7.2.
Go to the first foo, press Ctrl-v to enter visual block mode and press down until all the lines with foo are marked. Then press Shift-i to insert at the beginning (of the block). When you are finished and press Esc, the inserted characters will be added to each line at the left of the marked block.
To insert at the end, press again Ctrl-v, move up/down to mark all affected lines and then press End or $ to extend the selection until the end of the lines. Now you can press Shift-a to append at the end of all the lines, just like previously with Shift-i.
The visual selection can also be done with normal movement commands. So to comment a whole block in C you could move to the opening brace and type Ctrl-v % Shift-i // Esc.
To answer your first question, the below
:%s/foo/bar(&)/g
will look for foo, and surround the matched pattern with bar(). The /g will do this multiple times in one line.
Since you're just matching foo, you could do a simple :s/foo/bar(foo)/g. The above will work, however, if you decide to match on a regular expression rather than a simple word (e.g. f[a-z][a-z]). The '&' in the above represents what you've matched.
To prefix a set of lines I use one of two different approaches:
One approach is the block select (mentioned by sth). In general, you can select a rectangular region with ctrl-V followed by cursor-movement. Once you've highlighted a rectangle, pressing shift-I will insert characters on the left side of the rectangle, or shift-A will append them on the right side of the rectangle. So you can use this technique to make a rectangle that includes the left-most column of the lines you want to prefix, hit shift-I, type the prefix, and then hit escape.
The other approach is to use a substitution (as mentioned by Brian Agnew). Brian's substitution will affect the entire file (the % in the command means "all lines"). To affect just a few lines the easiest approach is to hit shift-V (which enables visual-line mode) while on the first/last line, and then move to the last/first line. Then type:
:s/^/YOUR PREFIX/
The ^ is a regex (in this case, the beginning of the line). By typing this in visual line mode you'll see '<,'> inserted before the s automatically. This means the range of the substitution will be the visual selection.
Extra tip: if your prefix contains slashes, you can either escape them with backslash, or you can use a different punctuation character as the separator in the command. For example, to add C++ line comments, I usually write:
:s:^:// :
For adding a suffix the substitution approach is generally easier unless all of your lines are exactly the same length. Just use $ for the pattern instead of ^ and your string will be appended instead of pre-pended.
If you want to add a prefix and a suffix simultaneously, you can do something like this:
:s/.*/PREFIX & SUFFIX/
The .* matches the whole line. The & in the replacement puts the matched text (the whole line) back, but now it'll have your prefix and suffix added.
BTW: when commenting out code you'll probably want to uncomment it later. You can use visual-block (ctrl-V) to select the slashes and then hit d to delete them, or you can use a substitution (probably with a visual line selection, made with shift-V) to remove the leading slashes like this:
:s:// ::
:normal to the rescue!
:%norm Wibar(
:%norm WEa)
:norm(al) replays the commands as if you had typed them:
W - goes to the next word
i - starts insertion mode
bar( - types the sequence 'bar('
Or in one line:
:%norm Wibar(ctrlvESCEa)
If you're running Windows then type ctrlq instead of ctrlv.
Yet another possibility (probably not-so-useful in your test case, but handy in other situations) is to cordon off the area you want to change with marks.
Put the cursor anywhere in the top line and press 'a
Put the cursor anywhere in the last line and press 'b
Issue the command :'a,'b s/foo/bar(&)/
I usually like visual block mode if everything is visible on the screen, and I usually prefer marks if the start and stop are separated by many screens.
Another simple regular expression is:
%s/^/<text you want to prepend>/
For the C-style comments, use the regexp answer by Brian, and match on line ending $, and insert away.