Nathan Lutterman
Nathan Lutterman

Reputation: 1885

Why does this Vim RegEx search and replace not match?

I'm attempting to use the following Vim RegEx pattern:

%s/\(<Column>[\ \t\nA-Za-z0-9\<\>\/]\+<Name>[ \t\n]*Code[ \t\n]*<\/Name>\([\ \t\nA-Za-z0-9\<\>\/]\)\{-}<\/Column>\)//g

I have also attempted:

%s/\v(\<Column\>[\s\w\<\>\/]+\<Name\>\s*Code\s*\<\/Name\>([\s\w\<\>\/]){-}\<\/Column\>)//g

The string I'm matching against has the form (of many lines) of this:

<Table>
  <Name>NameOfThing</Name>
  <Description>Description of thing</Description>
  <Type>Data</Type>
  <Columns>
    <Column>
      <Name>Code</Name>
      <Description>Things Code</Description>
      <Type>String</Type>
      <Length>254</Length>
    </Column>
    <Column>
      <Name>TypeCode</Name>
      <Description>Things type code</Description>
      <Type>String</Type>
      <Length>254</Length>
    </Column>
    <Column>
      <Name>Name</Name>
      <Description>Things Name</Description>
      <Type>String</Type>
      <Length>254</Length>
    </Column>
    ...
    ...
    ...

I am trying to capture and remove only the portion that looks like this:

    <Column>
      <Name>Code</Name>
      <Description>Things Code</Description>
      <Type>String</Type>
      <Length>254</Length>
    </Column>

When I convert the regular expression pattern syntax into something that PCRE accepts, it captures what I need correctly:

(<Column>[\s\w\<\>\/]+<Name>[ \t\n]*Code[ \t\n]*<\/Name>[\s\w\<\>\/]+?<\/Column>)

What am I missing here?


Edit: I am silly, my first attempt is working, but I had not fixed it in Vim after fixing it elsewhere.

However - I'm still curious as to why the other form with the magic \v does not work:

%s/\v(\<Column\>[ \t\nA-Za-z0-9\<\>\/]+\<Name\>[ \t\n]*Code[ \t\n]*\<\/Name\>[ \t\n\<\>\/]{-}\<\/Column\>)//g 

Upvotes: 0

Views: 440

Answers (2)

mattn
mattn

Reputation: 7723

\s is character class it-self. You can't use \s or \w in []. If you want to use it, you must use [[:space:]] instead. [\s] only match \ and s.

And you can use \_ modifier for .{-}. This can include the end-of-line.

%s/\v(\<Column\>\_.{-}\<Name\>\s*Code\s*\<\/Name\>\_.{-}\<\/Column\>)//g

Upvotes: 1

romainl
romainl

Reputation: 196556

I wouldn't use a substitution.

:g/>Code</-1,+4d

See:

:help :g
:help :range
:help :d

Upvotes: 0

Related Questions