8

I have googled this several times over the years and have not found a good solution so I am giving up and asking.

I want to be able to delete all words and punctuations that do not match a pattern.

So say i have this list

 R61,1,BWRBW0471,1
 R14,1,BWRBW0471,1
 R162,1,BWRBN0471,1
 R61 ,1,BWRBN0471,1
 R61 ,1,BWRBN0471,1
 R61 ,1,BWRBN0471,1

I want to remove everything BUT bwrb.*471,[0-9] so i am left with

BWRBW0471,1
BWRBW0471,1
BWRBW0471,1
BWRBW0471,1
BWRBW0471,1
BWRBW0471,1

Is there a easy VIM command that can accomplish?

thanks.

3 Answers 3

17
:%s/\v(.*)(bwrb.*471,\d)(.*)/\2

does what you want with your sample. It will probably need to be altered if your real world needs are more complex.

Basically, the pattern matches the whole line but we use grouping to separate what we want from what we don't. We get three groups, "before what we want", "what we want", "after what we want" and we replace the whole line with the second group, noted \1.

Step by step:

  • %s/

    The substitution is done on the whole file.

  • \v

    The "very magic" flag is useful for limiting the number of backslashes and improve legibility.

  • (.*)

    The first group contains any number of any character. Anchoring to the start of the line is implied so it matches whatever is before what you want. It would be \(.*\) without the "very magic" flag.

  • (bwrb.*471,\d)

    This is the second group: your pattern. The only thing I changed is [0-9] which I replaced with the equivalent but shorter \d.

  • (.*)

    The third group contains any number of any character up to the end of the line.

  • /\2

    The replacement part consist only in the second group.

6
  • could you add some information about the construction of this command to your answer?
    – dinesh
    Commented Mar 1, 2013 at 20:48
  • @dinesh, see my edit.
    – romainl
    Commented Mar 1, 2013 at 21:08
  • Thank, that is exactly what I needed as there are instances that items come after the pattern.
    – 7null
    Commented Mar 1, 2013 at 23:05
  • + 1 and my lifelong gratitude for introducing me to the "very magic" flag. Commented Apr 12, 2016 at 13:44
  • "very magic" flag, where have you been all my life?
    – ZeroG
    Commented Jul 1, 2017 at 19:38
3

I'd use this command:

%s/.*\(BWRB.*471,[0-9]\).*/\1

%: apply command to all lines of file.

s/pattern/replacement/: replacement command as use with sed:

  • .* matches any character until a substring matching \(BWRB.*471,[0-9]\) is found. Any characters after the substring are matched by .*. The parentheses instruct vi to save the substring.

  • The replacement \1 prints the previously saved substring, which in fact removes any unwanted characters from the line.

For instance, this file (which is your example slightly modified):

R61,1,BWRBW0471,2
R14,1,BWRBW0471,5
R162,1,BWRBN0471,0
R61 ,1,BWRBN0471,4
R61 ,1,BWRBN0471,1
R61 ,1,BWRBN0766471,1

is converted to:

BWRBW0471,2
BWRBW0471,5
BWRBN0471,0
BWRBN0471,4
BWRBN0471,1
BWRBN0766471,1
2
  • Thanks, that works also but only if there is nothing after the pattern. Which i guess i dont always know.
    – 7null
    Commented Mar 1, 2013 at 23:06
  • I see, I've modified my answer to take that into account.
    – jaume
    Commented Mar 1, 2013 at 23:10
2

I'm not sure quite how much variability there is preceding your strings, but it sounds like you just want a simple "replace up to BWRB on every line".

:%s/.*\zeBWRB//g

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .