2

I have a giant svg file with "two" colors. I need to suppress one of the colors, but it is a purge to do it graphicaly with Inkscape for example. So I try to do it by suppress the path corresponding to a pattern with vim.

There is a sample of the svg code with the differences :

       <path
          d="M 2014.7943429424638 4.082663308900636 L2014.7943429424638 2.041331654450318 L2016.835674596914 2.041331654450318 L2016.835674596914 4.082663308900636 Z"
          style="fill:rgb(41, 41, 41, 255)"
          id="path1437" />
       <path
          d="M 2018.8770062513645 6.123994963350954 L2016.835674596914 6.123994963350954 L2016.835674596914 4.082663308900636 L2016.835674596914 2.041331654450318 L2018.8770062513645 2.041331654450318 L2018.8770062513645 4.082663308900636 Z"
          style="fill:rgb(255, 255, 255, 255)"
          id="path1439" />
       <path
          d="M 2018.8770062513645 4.082663308900636 L2018.8770062513645 2.041331654450318 L2020.9183379058147 2.041331654450318 L2020.9183379058147 4.082663308900636 Z"
          style="fill:rgb(42, 42, 42, 255)"
          id="path1441" />
       <path
          d="M 2022.9596695602652 6.123994963350954 L2020.9183379058147 6.123994963350954 L2020.9183379058147 4.082663308900636 L2022.9596695602652 4.082663308900636 L2025.0010012147154 4.082663308900636 L2025.0010012147154 6.123994963350954 L2022.9596695602652 6.123994        963350954 L2020.9183379058147 6.123994963350954 L2020.9183379058147 4.082663308900636 L2022.9596695602652 4.082663308900636 L2022.9596695602652 6.123994963350954 L2022.9596695602652 8.165326617801272 L2020.9183379058147 8.165326617801272 L2018.8770062513645 8.16532        6617801272 L2018.8770062513645 6.123994963350954 L2020.9183379058147 6.123994963350954 L2022.9596695602652 6.123994963350954 L2022.9596695602652 8.165326617801272 L2020.9183379058147 8.165326617801272 L2020.9183379058147 6.123994963350954 L2020.9183379058147 2.0413        31654450318 L2022.9596695602652 2.041331654450318 L2022.9596695602652 4.082663308900636 Z"
          style="fill:rgb(255, 255, 255, 255)"
          id="path1443" />
       <path
          d="M 2022.9596695602652 4.082663308900636 L2022.9596695602652 2.041331654450318 L2025.0010012147154 2.041331654450318 L2025.0010012147154 4.082663308900636 Z"
          style="fill:rgb(250, 250, 250, 255)"
          id="path1445" />
       <path
          d="M 2025.0010012147154 4.082663308900636 L2025.0010012147154 2.041331654450318 L2027.0423328691656 2.041331654450318 L2027.0423328691656 4.082663308900636 Z"
          style="fill:rgb(255, 255, 255, 255)"
          id="path1447" />
       <path
          d="M 2027.0423328691656 4.082663308900636 L2027.0423328691656 2.041331654450318 L2029.083664523616 2.041331654450318 L2029.083664523616 4.082663308900636 Z"
          style="fill:rgb(251, 251, 251, 255)"
          id="path1449" />
       <path
          d="M 2029.083664523616 4.082663308900636 L2029.083664523616 2.041331654450318 L2031.1249961780663 2.041331654450318 L2031.1249961780663 4.082663308900636 Z"
          style="fill:rgb(36, 36, 36, 255)"
          id="path1451" />

The aim is to suppress the white color's path, but as you can see, it is never pure white. It's nuances from 240 to 251 in each RGB channels.

Until now, I found this regex pattern :

/<path\nd="[ .MLZ0-9]+"\nstyle="fill:rgb\([0-9]{3}, [0-9]{3}, [0-9]{3}, 255\)"\nid="path[0-9]+" />/g

It seems to work on https://regexr.com, but I don't know how to use it with vim.

Any ideas ?

I can provide a svg file if you want to test it, but it's usually ~140MB files...

1
  • Might be off-topic, but I don't think a huge vim regex is a good solution. It's hard to construct and maintain. For your task, python, perl or awk would be better.
    – Hoblovski
    Aug 3, 2023 at 11:38

1 Answer 1

1

Regexr doesn't support Vim's regular expression dialect so using it to craft Vim regular expressions is rather pointless. And, well, your pattern doesn't work with the provided sample in regexr anyway.

Here are the changes to apply for your pattern to work in Vim:

  1. Fix some quantifiers

    {3} is a literal {3}. You need to escape it to make it a quantifier: \{3} (or \{3\}).

    Result:

    /<path\nd="[ .MLZ0-9]+"\nstyle="fill:rgb\([0-9]\{3}, [0-9]\{3}, [0-9]\{3}, 255\)"\nid="path[0-9]+" />
    
  2. Fix more quantifiers

    + is a literal +. You need to escape it to make it a quantifier: \+.

    Result:

    /<path\nd="[ .MLZ0-9]\+"\nstyle="fill:rgb\([0-9]\{3}, [0-9]\{3}, [0-9]\{3}, 255\)"\nid="path[0-9]\+" />
    
  3. Fix parentheses

    \( and \) are used to create a "capture" group. Use ( and ) for literal parentheses.

    Result:

    /<path\nd="[ .MLZ0-9]\+"\nstyle="fill:rgb([0-9]\{3}, [0-9]\{3}, [0-9]\{3}, 255)"\nid="path[0-9]\+" />
    
  4. Fix indenting

    All the lines are indented so the text of next line doesn't start immediately after the \n. You need something like \s* for "any number of leading whitespace character".

    Result:

    <path\n\s*d="[ .MLZ0-9]\+"\n\s*style="fill:rgb([0-9]\{3}, [0-9]\{3}, [0-9]\{3}, 255)"\n\s*id="path[0-9]\+" />
    
  5. Fix slashes

    If you use / to search, you must escape the /s in the pattern.

    Result:

    <path\n\s*d="[ .MLZ0-9]\+"\n\s*style="fill:rgb([0-9]\{3}, [0-9]\{3}, [0-9]\{3}, 255)"\n\s*id="path[0-9]\+" \/>
    

matches

(The pink match is the current match, YMMV)

Without an online tool, constructing a complex pattern in Vim itself is not that hard, especially with the latest changes in :help 'incsearch'.

Now, if the goal is to get rid of those matching <path>s, constructing such a complex and overly literal pattern doesn't seem to be a good use of anyone's time. The almighty :help :global is made for scenarios like this:

:g/rgb([0-9]\{3}, [0-9]\{3}, [0-9]\{3}, 255)/?<path?,/id=/d

where ?<path?,/id=/d is the command :help :d with a :help :range:

  • the matched line with a specific rgb(… is marked as current line by :global,
  • ?<path? searches for <path before the current line, see :help ?,
  • /id=/ searches for the first id= after the current line, see :help /.

In other words: "for every line with a specific rgb(…, delete everything from the first <path line that comes before it to the first id= line that comes after it".

At an even higher level: "for every line with X, do something on an arbitrary range of lines around that line".

Or, even simpler:

:g/rgb([0-9]\{3}, [0-9]\{3}, [0-9]\{3}, 255)/normal da<

where normal da< simply executes the normal mode command da< on the matching lines. See :help d and :help a<.

2
  • 1
    Thank you so much. I didn't knew these global way to delete lines. Could you detail the end of the commands ? The ?<path?,/id=/id or normal da< parts ?
    – sh_k_
    Aug 2, 2023 at 2:30
  • 1
    OK, I've updated my answer.
    – romainl
    Aug 2, 2023 at 6:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.