Jason Down
Jason Down

Reputation: 22151

What Vim command to use to delete all text after a certain character on every line of a file?

Scenario:

Is it possible, using Vim to delete all data from the second pipe to the end of the line for the entire file? There are approx 150,000 lines, so doing this manually would only be appealing to a masochist...

For example, change the following lines from:

1111|random sized text 12345|more random data la la la|1111|abcde
2222|random sized text abcdefghijk|la la la la|2222|defgh
3333|random sized text|more random data|33333|ijklmnop

to:

1111|random sized text 12345
2222|random sized text abcdefghijk
3333|random sized text

I'm sure this can be done somehow... I hope.

UPDATE: I should have mentioned that I'm running this on Windows XP, so I don't have access to some of the mentioned *nix commands (cut is not recognized on Windows).

Upvotes: 16

Views: 9630

Answers (12)

Rob Wells
Rob Wells

Reputation: 37103

Why use Vim? Why not just run

cat my_pipe_file | cut -d'|' -f1-2

Upvotes: 0

PEZ
PEZ

Reputation: 17004

This will filter all lines in the buffer (1,$) through cut to do the job:

:1,$!cut -d '|' -f 1-2

To do it only on the current line, try:

:.!cut -d '|' -f 1-2

Upvotes: 0

ghostdog74
ghostdog74

Reputation: 342263

Use Awk:

awk -F"|" '{$0=$1"|"$2}1' file

Upvotes: 1

graywh
graywh

Reputation: 9840

You can use :command to make a user command to run the substitution:

:command -range=% YourNameHere <line1>,<line2>s/^\v([^|]+\|[^|]+)\|.*$/\1/

Upvotes: 2

Luc Hermitte
Luc Hermitte

Reputation: 32926

Just another Vim way to do the same thing:

%s/^\(.\{-}|\)\{2}\zs.*//
%s/^\(.\{-}\zs|\)\{2}.*//  " If you want to remove the second pipe as well.

This time, the regex matches as few characters as possible (\{-}) that are followed by |, and twice (\{2}), they are ignored to replace all following text (\zs) by nothing (//).

Upvotes: 4

Paul Tomblin
Paul Tomblin

Reputation: 182772

If you don't have to use Vim, another alternative would be the unix cut command:

cut -d '|' -f 1-2 file > out.file

Upvotes: 8

Christian C. Salvad&#243;
Christian C. Salvad&#243;

Reputation: 827198

You can also record a macro:

qq02f|Djq

and then you will be able to play it with 100@q to run the macro on the next 100 lines.

Macro explanation:

  • qq: starts macro recording;
  • 0: goes to the first character of the line;
  • 2f|: finds the second occurrence of the | character on the line;
  • D: deletes the text after the current position to the end of the line;
  • j: goes to the next line;
  • q: ends macro recording.

Upvotes: 18

ib.
ib.

Reputation: 28934

Instead of substitution, one can use the :normal command to repeat a sequence of two Normal mode commands on each line: 2f|, jumping to the second | character on the line, and then D, deleting everything up to the end of line.

:%norm!2f|D

Upvotes: 4

unbeknown
unbeknown

Reputation:

Here is a sed solution:

sed -e 's/^\([^|]*|[^|]*\).*$/\1/'

Upvotes: 0

Jay
Jay

Reputation: 42632

You can also do:

:%s/^\([^\|]\+|[^\|]\+\)\|.*$/\1/g

Upvotes: 1

Sarel Botha
Sarel Botha

Reputation: 12700

I've found that vim isn't great at handling very large files. I'm not sure how large your file is. Maybe cat and sed together would work better.

Upvotes: 0

Brian Carper
Brian Carper

Reputation: 72926

:%s/^\v([^|]+\|[^|]+)\|.*$/\1/

Upvotes: 31

Related Questions