1

I would like to ...

  • replace the hexadecimal code for URL (id) in all SVG files
  • insert/add the new lines of SVG codes after <svg ...>, using Regex.

Input:

<svg xmlns="http://www.w3.org/2000/svg" style="isolation:isolate" width="16" height="16" viewBox="0 0 16 16">
 <defs>
  <clipPath id="clip1">
   <rect width="16" height="16"/>
  </clipPath>
 </defs>
 <g clip-path="url(#clip1)">
  <rect fill="#5c616c" width="4.625" height="3.594" x="18.19" y="-.16" transform="matrix(1,0,0,1,0,0)"/>
  <path fill="#5c616c" d="M 11.538 1 L 11.166 1.46 L 9.895 3.082 L 8.712 3.082 L 8.712 3.783 L 5.908 3.783 L 5.908 5.185 L 8.712 5.185 L 8.712 5.886 L 9.895 5.886 L 11.166 7.507 L 11.538 7.967 L 12.042 7.704 L 15 6.149 L 14.342 4.922 L 11.911 6.193 L 10.596 4.484 L 11.91 2.774 L 14.343 4.046 L 15 2.819 L 12.042 1.263 L 11.538 1 Z M 3.103 2.38 C 1.911 2.38 1 3.292 1 4.484 C 1 5.376 1.512 6.121 2.271 6.433 L 3.935 11.495 L 6.894 11.495 L 4.943 5.514 C 5.11 5.209 5.207 4.864 5.207 4.484 C 5.207 3.292 4.295 2.38 3.103 2.38 Z M 3.103 3.783 C 3.525 3.783 3.804 4.062 3.804 4.484 C 3.804 4.906 3.525 5.185 3.103 5.185 C 2.681 5.185 2.402 4.906 2.402 4.484 C 2.402 4.062 2.681 3.783 3.103 3.783 Z M 2.402 12.196 C 1.63 12.196 1 12.825 1 13.598 L 1 15 L 12.918 15 L 12.918 13.598 C 12.918 12.825 12.289 12.196 11.516 12.196 L 2.402 12.196 Z"/>
 </g>
</svg>

Output:

<svg xmlns="http://www.w3.org/2000/svg" style="isolation:isolate" width="16" height="16" viewBox="0 0 16 16">

<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
  <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
  <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
</linearGradient>

 <defs>
  <clipPath id="clip1">
   <rect width="16" height="16"/>
  </clipPath>
 </defs>
 <g clip-path="url(#clip1)">
  <rect fill="url(#grad1)" width="4.625" height="3.594" x="18.19" y="-.16" transform="matrix(1,0,0,1,0,0)"/>
  <path fill="url(#grad1)" d="M 11.538 1 L 11.166 1.46 L 9.895 3.082 L 8.712 3.082 L 8.712 3.783 L 5.908 3.783 L 5.908 5.185 L 8.712 5.185 L 8.712 5.886 L 9.895 5.886 L 11.166 7.507 L 11.538 7.967 L 12.042 7.704 L 15 6.149 L 14.342 4.922 L 11.911 6.193 L 10.596 4.484 L 11.91 2.774 L 14.343 4.046 L 15 2.819 L 12.042 1.263 L 11.538 1 Z M 3.103 2.38 C 1.911 2.38 1 3.292 1 4.484 C 1 5.376 1.512 6.121 2.271 6.433 L 3.935 11.495 L 6.894 11.495 L 4.943 5.514 C 5.11 5.209 5.207 4.864 5.207 4.484 C 5.207 3.292 4.295 2.38 3.103 2.38 Z M 3.103 3.783 C 3.525 3.783 3.804 4.062 3.804 4.484 C 3.804 4.906 3.525 5.185 3.103 5.185 C 2.681 5.185 2.402 4.906 2.402 4.484 C 2.402 4.062 2.681 3.783 3.103 3.783 Z M 2.402 12.196 C 1.63 12.196 1 12.825 1 13.598 L 1 15 L 12.918 15 L 12.918 13.598 C 12.918 12.825 12.289 12.196 11.516 12.196 L 2.402 12.196 Z"/>
 </g>
</svg>

Here is my shell script:

for i in *.svg; 
    do sed --in-place --follow-symlinks 's/#5c616c/url(#grad1)/' "$i"
done;

for i in *.svg; 
    do sed --in-place --follow-symlinks '/(svg)([^<]*|[^>]*)/ag <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%"> <stop offset="0%" style="stop-color: rgb(255, 255, 0); stop-opacity: 1"\/> <stop offset="100%" style="stop-color: rgb(255, 0, 0); stop-opacity: 1"\/> <\/linearGradient>' "$i"
done;

In one line:

for i in *.svg; do sed --in-place --follow-symlinks 's/#5c616c/url(#grad1)/g; /(svg)([^<]*|[^>]*)/a <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%"> <stop offset="0%" style="stop-color: rgb(255, 255, 0); stop-opacity: 1"\/> <stop offset="100%" style="stop-color: rgb(255, 0, 0); stop-opacity: 1"\/> <\/linearGradient>' "$i"; done

My commands are not good, because it replaced and inserted some SVG files, and destroyed others.

Based:

Updated

Based on:

I have an icons theme called Breeze. Firstly I want to find that an icons theme is in /usr/share/icons/breeze, /home/$USER/.icons/breeze or /home/$USER/.local/share/icons/breeze, and if it is found, I will cd it and then replace and insert in all SVG files in multiples folders (not all folders). Three folders: apps/16, mimetypes/16 and places/16.

Is it possible to re-adapt with these codes derived of links in the file replace-all.sh?

  • What is the second sed command trying to replace? You seem to be trying to replace all occurrences of the string svg followed by anything at all ([^<]* will match 0 or more non-<). Can you edit your question and clarify that? Also, obligatory reading: RegEx match open tags except XHTML self-contained tags – terdon Jan 5 at 23:33
  • It is not to replace, it is to add new text just after the <svg ...>. As for the question, in spite of the answer being very reasonable, there are other answers arguing that it is possible to use XHTML with Regex only if the codes are not big. – Gustavo Reis Jan 6 at 0:52
0

If I understand correctly, you want to do two things:

  1. Replace the #5c616c with url(#grad1).
  2. Insert these lines after the opening <svg ...> tag:

    <linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
      <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
      <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
    </linearGradient>
    

Personally, I'd just do the whole thing in Perl:

#!/bin/perl
my $replacement=<<EoF;
<linearGradient id="grad1" x1="0%" y1="0%" x2="100%" y2="0%">
  <stop offset="0%" style="stop-color:rgb(255,255,0);stop-opacity:1" />
  <stop offset="100%" style="stop-color:rgb(255,0,0);stop-opacity:1" />
</linearGradient>
EoF
## This is just to fix SE's syntax highlighting /    
my $foundSvg = 0;
while (<>) {
  ## Insert the replacement after the 1st line matching '<svg'
  if (/<\s*svg/) {
    $foundSvg++;
  }
  if ($foundSvg == 1) {
    ## $_ is the value of the current line. If we have found the <svg,
    ## append $replacement to this line
    $_ .= $replacement;
    ## Increment $foundSvg so we don't do this twice
    $foundSvg++;
  }
  ## For all lines, replace all occurrences of #5c616c with url(#grad1)
  s/#5c616c/url(#grad1)/g;
  ## Print the line
  print;
}

Save that as foo.pl and then:

for f in *svg; do
   perl foo.pl "$f" > tmpFile && mv tmpFile "$f"
done
  • sorry, I forgot of adding something in my question. I have just updated. I am not sure if it possible to replace and insert in all SVG files in multiple specific folders only if the icons theme is found somewhere, using replace-all.sh. – Gustavo Reis Jan 6 at 1:50
  • @GustavoReis please post that as a new question, and include the code you are using in this replace-all.sh. – terdon Jan 6 at 3:05
  • ready. Here is the unix.stackexchange.com/questions/492755/…. – Gustavo Reis Jan 6 at 5:07
  • Hey, @terdon, you forgot of preserving the symlinks. The perl file destroyed the symlinks. – Gustavo Reis Jan 6 at 20:47
  • @GustavoReis oh, I didn't know that was a requirement. I was wondering why you were using the --follow-symlinks option. You can keep the symlinks if you run: for f in *svg; do; perl foo.pl "$f" > tmpFile && mv tmpFile "$(readlink -f "$f")"; done. – terdon Jan 6 at 21:27

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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