15

Say I have the following style of lines in a text file:

"12" "34" "some text     "
"56" "78" "some more text"
.
.
.
etc.

I want to be able to remove the quotes surrounding the first two columns. What is the best way to do this with Vim (I'm currently using gVim)?

I figured out how to at least delete the beginning quote of each line by using visual mode and then enter the command '<,'>s!^"!!

I'm wondering if there is a way to select an entire column of text (one character going straight down the file... or more than 1, but in this case I would only want one). If it is possible, then would you be able to apply the x command (delete the character) to the entire column.

There could be better ways to do it. I'm looking for any suggestions.


Update

Just and FYI, I combined a couple of the suggestions. My _vimrc file now has the following line in it:

let @q=':%s/"\([0-9]*\)"/\1/g^M'   

(Note: THE ^M is CTRLQ + Enter to emulate pressing the Enter key after running the command)

Now I can use a macro via @q to remove all of the quotes from both number columns in the file.

kenorb
  • 155,785
  • 88
  • 678
  • 743
Jason Down
  • 21,731
  • 12
  • 83
  • 117

8 Answers8

28

use visual block commands:

  • start mode with Ctrl-v
  • specify a motion, e.g. G (to the end of the file), or use up / down keys
  • for the selected block specify an action, e.g. 'd' for delete

For more see :h visual-mode

Fritz G. Mehner
  • 16,550
  • 2
  • 34
  • 41
19

Control-V is used for block select. That would let you select things in the same character column.

It seems like you want to remove the quotes around the numbers. For that use,

:%s/"\([0-9]*\)"/\1/g

Here is a list of what patterns you can do with vim.


There is one more (sort of ugly) form that will restrict to 4 replacements per line.

:%s/^\( *\)"\([ 0-9]*\)"\([ 0-9]*\)"\([ 0-9]*\)"/\1\2\3\4/g

And, if you have sed handy, you can try these from the shell too.

head -4 filename.txt | sed 's/pattern/replacement/g'

that will try your command on the first 4 lines of the file.

nik
  • 13,254
  • 3
  • 41
  • 57
  • I was able to do block selecting and deleting in ED4W (different editor), so I figured Vim must let you do something similar. However, you're right in what I really want is to remove quotes from around the numbers. This is exactly what I was looking for. Thank you! – Jason Down Jun 22 '09 at 17:30
  • This actually removed the quotes around the other text as well (the third column). I'm sure I can play around with it to make it work though. – Jason Down Jun 22 '09 at 17:39
  • Did other columns also have plain numbers with quotes? else it wouldn't do that. – nik Jun 22 '09 at 18:09
  • No, none of them do. Very strange, because from what I can tell in the documentation, your example should work perfectly. – Jason Down Jun 22 '09 at 18:15
  • That is very odd, I am adding a variation for you to check. – nik Jun 22 '09 at 18:29
  • Works for my situation, since this file will always be generated with the exact same format. I had to change the command from :s to :%s to make it work, but other than that, worked like a charm. – Jason Down Jun 22 '09 at 18:38
  • 1
    I liked your first example the best. I made one modification and this seemed to work: :%s/"\([0-9]*\)\"/\1/g or could use :%s/"\([0-9]*\)\"/\1/g – Jason Down Jun 22 '09 at 19:03
  • Guess what! i had another typo right in the first example. Figures why you couldn't use it :-( i must be sleepy or something. Fixing immediately. – nik Jun 22 '09 at 19:06
  • Its funny how once you have solved something, it really takes another person to find such bugs. Your mind has sort of blocked-out the 'fixed' part! You clearly pointed out that it did not work, and yet i never got around looking at that missing ". So did your other columns start with numbers? that would explain my bug manifesting. – nik Jun 22 '09 at 19:09
  • You don't need to escape the quote. The first answer i gave (alas with a typo) was the actual answer. Others should be used just to learn a bit more about these pattern techniques. – nik Jun 22 '09 at 19:13
  • Actually, escaping the quote was a typo on my part lol. Regular expressions are not nice on the eyes... – Jason Down Jun 22 '09 at 19:19
4

Say if you want to delete all columns but the first one, the simple and easy way is to input this in Vim:

:%!awk '{print $1}'

Or you want all columns but the first one, you can also do this:

:%!awk '{$1="";$0=$0;$1=$1;print}'

Indeed it requires external tool to accomplish the quest, but awk is installed in Linux and Mac by default, and I think folks with no UNIX-like system experience rarely use Vim in Windows, otherwise you probably known how to get a Windows version of awk.

Meow
  • 4,341
  • 1
  • 18
  • 17
  • Due to the line reconstruction of the second one's side effect, you might want to specify the OFS variable in awk code. – Meow Oct 10 '13 at 10:32
  • This is old... but at the time I didn't have access to awk (except maybe through something like cygwin or unxutils). That's not to say this isn't a valid solution. – Jason Down Oct 10 '13 at 14:24
  • I tested gawk from [gnuwin32](http://gnuwin32.sourceforge.net/packages/gawk.htm)(a little bit old though), I put the binary within the same directory of gvim.exe, and it worked fine. – Meow Oct 11 '13 at 00:35
  • Cool. Seems like there are many workable solutions to this question. – Jason Down Oct 11 '13 at 14:27
  • What does the $0=$0 do? – cokedude Apr 21 '14 at 02:38
3

See column editing in vim. It describes column insert, but basically it should work in the same way for removing.

wazoox
  • 1,384
  • 16
  • 27
3

Although this case was pretty simple to fix with a regex, if you want to do something even a bit more advanced I also recommend recording a macro like Bryan Ward. Also macros come easier to me than remembering which characters need to be escaped in vim's regexes. And macros are nice because you can see your changes take place immediately and work on your line transformation in smaller bits at a time.

So in your case you would have pressed qw to start recording a macro in register w (you can of course use any letter you want). I usually start my macros with a ^ to move to the start of the line so the macro doesn't rely on the location of the cursor. Then you could do a f" to jump to the first ", x to delete it, f" to jump to the next " and x to delete that too. Then q to finish recording.

Instead of making your macro end on the next line I actually as late as today figured out you can just V (visually line select) all lines you want to apply your macro to and execute :normal @w which applies your macro in register w to each visually selected line.

Sam
  • 14,642
  • 6
  • 27
  • 39
  • I haven't done much with Macros, but I can see them being very useful. This is something I have to do often enough that I need a convenient way to do it, but I don't do it enough that remembering the regex would be easy. A macro is probably the better solution in this case (though I really should work on master regex... as they come in handy for programming in .NET as well). – Jason Down Jun 22 '09 at 18:26
1

You could also create a macro (q) that deletes the quotes and then drops down to the next line. Then you can run it a bunch of times by telling vi how many times to execute it. So if you store the macro to say the letter m, then you can run 100@m and it will delete the quotes for 100 lines. For some more information on macros:

http://vim.wikia.com/wiki/Macros

Bryan Ward
  • 6,443
  • 8
  • 37
  • 48
1

The other solutions are good. You can also try...

:1,$s/^"\(\w\+\)"/\1/gc

For more Vim regex help also see http://vim.wikia.com/wiki/Search_patterns.

adelarsq
  • 3,718
  • 4
  • 37
  • 47
kervin
  • 11,672
  • 5
  • 42
  • 59
  • Tried it out (I removed the c to get rid of the confirm mode, but kept it the same other than that). It seemed to only remove the quotes around the first column. – Jason Down Jun 22 '09 at 17:42
  • Right, to do just the first two you'd use: :%s/^"\\(\d\+\\)"\s\+"\\(\d\+\\)"/\1 \2/ If the space between the numbers is important, you can capture that too: :%s/^"\\(\d\+\\)"\\(\s\+\\)"\\(\d\+\\)"/\1\2\3/ – TMN Jun 22 '09 at 18:24
1
  1. Start visual-block by Ctrl+v.
  2. Jump at the end and select first two columns by pressing: G, EE.
  3. Type: :s/\%V"//g which would result in the following command:

    :'<,'>s/\%V"//g
    

    Press Enter and this will remove all " occurrences in the selected block.

See: Applying substitutes to a visual block at Vim Wikia

kenorb
  • 155,785
  • 88
  • 678
  • 743