user1228191
user1228191

Reputation: 681

Delete a specific Column in VIM/gvim with out using Visual Block mode

Sample Input File

+--------------------+---------+---------
|           Name     |   S1    |    S2
+--------------------+---------+---------
|           A        | -4.703  | -2.378  
|           B        | -3283.2 | -3204.5 
|           C        |  8779   |  7302   
|           D        |  22078  |  18018  
+--------------------+---------+---------

It is required to remove the S1 Column, i.e

Desired Output

+--------------------+---------
|           Name     |   S2    
+--------------------+---------
|           A        | -2.378    
|           B        | -3205.5  
|           C        |  7302      
|           D        |  18018    
+--------------------+---------

Can anyone help with this

thanks

Upvotes: 8

Views: 8944

Answers (6)

Alan Gómez
Alan Gómez

Reputation: 378

You can use a simple regex like:

:%s/\%>21c.*\%<32c//g

Upvotes: 0

kenorb
kenorb

Reputation: 166309

Based on patterns of your table, this can be achieved in two simple commands:

:%norm 2f+dF+
:%norm 2f|dF|

Where 2 is your column to remove (1 will remove 1st, 3 - 3rd).

This works as below (for each line at once):

  1. Find second corresponding character of the column (2f+ or 2f|).
  2. Delete backwards to the next found character of the column (dF+ or dF|).

Here is command line approach removing 2nd column in-place:

$ ex +'%norm 2f+dF+' +'%norm 2f|dF|' -scx cols2

Upvotes: 0

sehe
sehe

Reputation: 392843

Look, ma: no visual (block) mode !

My pragmatic approach wins would be: look for column anchors (-+-)

/-+-

Now, the column deletion is as simple as

d<C-v>N

(delete, block-wise, to the next occurrence of the column anchor from the end of the document).

Job done.


Fancy options

To account for multiple columns, you'd like to be precise about which column to match

This needs a little extra oomph

0f+
:exec '/\%' . col('.') . 'v\v[+|]'Enter
NC-vN
t+d

To see more about this \%22v way to select a virtual column, see

Upvotes: 4

Magnun Leno
Magnun Leno

Reputation: 2738

If this is the only content of the file, the simplest way is to use this:

:%normal 22|d32|

IF there is more text in the file, specifies the line interval:

:X,Ynormal 22|d32|

Where X and Y is the line interval, for example: 10,17normal 22|d32|

If you're not familiar with the normal command and with the | "motion" there goes a quick explanation:

  1. The normal command execute the following commands in the normal mode;
  2. The | "motion" moves the cursor to a specified column, so 22| moves the cursor to the 22nd column;

Basically what :X,Ynormal 22|d32|does is to move the cursor to the 22nd column (22|) and deletes everything (d) until the 32nd column (32|) for every line specified by X and Y.

Upvotes: 2

Tim Pote
Tim Pote

Reputation: 28029

In command mode:

:%s/^\([[+|][^+|]\+\)[+|][^+|]\+/\1/

This uses vim's built-in sed-like search and replace command. Here's the breakdown:

% - for the entire file

s - search for

/^ - the start of line

\([[+|][^+|]\+\) - followed by + or |, followed by any number (\+) of anything that is not + or |. This will get the first column, which we want to keep, so put it in a capture group by surrounding it with \( and \)

[+|][^+|]\+ - followed by + or |, followed by any number (\+) of anything that is not + or |. This will get the second column, which we don't want to keep, so no capture group.

/\1/ - replace everything we matched with the first capture group (which contains the first column). This effectively replaces the first and second column with the contents of the first column.

Like I said, vim's regex are pretty much identical to sed, so you if you look through this tutorial on sed you'll probably pick up a lot of useful stuff for vim as well.

Edit

In response to the OP's request to make this more generally capable of deleting any column:

:%s/^\(\([[+|][^+|]\+\)\{1\}\)[+|][^+|]\+/\1/

The index inside of the \{\}, now deletes the column indicated. Think of it like an array index (i.e. starts at zero). So \{0\} now deletes the first column, \{1\} deletes the second, and so on.

Upvotes: 3

Birei
Birei

Reputation: 36252

I would like to write Mathias Schwarz's comment into an answer because Visual Mode is the natural way for the task, although there is already an accepted answer.

Assuming cursor is in ¶

+--------------------+¶--------+---------
|           Name     |   S1    |    S2  
+--------------------+---------+---------
|           A        | -4.703  | -2.378  
|           B        | -3283.2 | -3204.5 
|           C        |  8779   |  7302   
|           D        |  22078  |  18018  
+--------------------+---------+---------

Use normal command Ctrl-V8jf+d to select S1 column and delete it. Explanation:

  • Ctrl-V: Enter in Blockwise Visual Mode.
  • 8j: Eigth is the number of rows of the table, it sets cursor at same column but last line.
  • f+: Move cursor until next + character.
  • d: delete visual selection.

And result is:

+--------------------+---------
|           Name     |    S2
+--------------------+---------
|           A        | -2.378  
|           B        | -3204.5 
|           C        |  7302   
|           D        |  18018  
+--------------------+---------

Upvotes: 3

Related Questions