tags:

views:

692

answers:

8
+3  Q: 

Columns in VI

I have a bunch of lines that I'd like to split into two columns, and get the data from each column. The data looks something like this:

current_well.well_number
current_well.well_name
current_well.well_type_code
well_location.section
well_location.range

Essentially what I'd like to do is split the line based off of the period, turn the data into two columns, and then grab the data for each column. I know this can be done in Excel, but I'm really interested in VIs solution for this problem. I know that

%s/./

will format the string with empty spaces. But once I have the data looking like:

current_well well_number
current_well well_name
current_well well_type_code
well_location section
well_location range

How do I grab all the values for each column so I can paste it into another application?

Thanks for your help!

A: 

One possible solution:

  1. w (or W for WORDS) jumps to next word,
  2. CTRL-R CTRL-W gets the word under cursor and pastes it into command-line

Now you have to chain those commands in a loop and then output them in your own manner.

alvatar
A: 

Why not block visual mode ? C-v, select what you want, and paste it in some other application. For that kind of pasting, you should probably set

:set guioptions+=a

as well.

Hmm, now that I've re-read your question. Are you asking how to divide the data into columns, or how to paste it in some other app ?


I think I got it now (3rd reading).

Do as you've done and get the spaces where the dots used to be. Then do another substitution, and replace the spaces with tabs, each tab being, 15 or something. It will line them up nicely. Then you can select and copy them to wherever.

You can also match the regex to select the second column for example, but although it is light up like a christmas tree, you won't be able to yank it.

ldigas
A: 

You can select columns in gvim by typing either <Ctrl-V><Ctrl-G> or <Ctrl-Q><Ctrl-G> (depending on if you are using windows insert key mappings) and then selecting with the mouse.

anon
A: 

Ctrl V selects a column

Martin Beckett
Actually, it selects a block. I've yet to find an editor which can select columns of text.
ldigas
A: 

I'd convert the dots to tabs, then block select each column:

:%s/\./CtrlV-Tab/g

CtrlV to then block select the columns.

Or, as you'd have tab separated values, they will paste directly into columns in Excel.

Andy Whitfield
+2  A: 

I've run into this problem a number of times. Changing the dots to tabs will line them up mostly nice, but not really. It's true that all the columns will start on a tabstop, but there's no guarantee that they'll be on the same tabstop. For instance, if this was your original text:

lt1tab.value1
gt1tabstop.value2

and you do:

%s/\./\t/g

and assuming a tabstop is 8 spaces, you'll get:

lt1tab  value1
gt1tabstop    value2

What you might want to do instead is remove everything but the last column (or whichever column you want). For instance:

%s/^.*\.//

will leave you with:

value1
value2

Which you can easily copy and paste.


If you don't have to use Vim, you can use unix's cut to do what you want:

cut -f2 -d. input_file > output_file
Nathan Fellman
This worked great! To get values left of the period I used the following expression:%s/\..*$//
Blake Blackwell
+1  A: 

Obviously, the above methods with block select and/or Excel are easier. But I'm a masochist and I decided to assume you didn't have access to either of those and try to do it with only vi commands. Here's the horrible thing I thought up:

My basic plan is to turn the list of joined columns into two lists, one after the other. This basically involves breaking each row into two lines, then copying every other line to the end of the file.

So, first we have to break each line into two lines with this command:

:%s/\./^M/

Next, swing by the bottom of the file and create an empty line, then return to the first line. This will help with readability later.

Go[Esc]
:1

Now, you need to map the following sequence to your favorite key:

:map [Key] mkjddGp'kj

(For the record, this marks the current row, deletes the row below it, pastes that row at the bottom of the file, returns to the row you started from, and then moves to the next row.)

Finally, press the mapped key once for every row in your list. So, with the example list, you'd press it 5 times. Make sure you start from the first line in the list!!

What you'll have at the end is the following:

current_well
current_well
current_well
well_location
well_location

well_number
well_name
well_type_code
section
range

You can now easily copy each list to wherever you need to put them.

abeger
+3  A: 

One option is to use this Align plugin to line up the periods so you can more easily select a column in Visual Block mode. e.g. if you do this:

:%Align \.

You'll end up with:

current_well  . well_number
current_well  . well_name
current_well  . well_type_code
well_location . section
well_location . range

If you don't want to use a plugin, try padding your columns with spaces. e.g. for your text:

:%s/\v(.*)\.(.*)/\=printf("%-16s %s", submatch(1), submatch(2))/

That'll leave you with:

current_well     well_number
current_well     well_name
current_well     well_type_code
well_location    section
well_location    range

Then you can Ctrl-V and select a column of text to copy. Just make sure you pick a column width wider than your widest value.

Brian Carper
Wow, an excellent answer, I wasn't aware of printf/submatch in a substitution; thanks!
Dave Tapley