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?

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
Oo'-
  • 243
  • 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 05 '19 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. – Oo'- Jan 06 '19 at 00:52

1 Answers1

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
terdon
  • 242,166
  • 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. – Oo'- Jan 06 '19 at 01:50
  • @GustavoReis please post that as a new question, and include the code you are using in this replace-all.sh. – terdon Jan 06 '19 at 03:05
  • ready. Here is the https://unix.stackexchange.com/questions/492755/finding-a-specific-icons-theme-somewhere-to-cd-for-using-sed-to-replace-and-add. – Oo'- Jan 06 '19 at 05:07
  • Hey, @terdon, you forgot of preserving the symlinks. The perl file destroyed the symlinks. – Oo'- Jan 06 '19 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 06 '19 at 21:27
  • It preserved the symlinks, but it made all files unusual. See the screenshot here. You can download my archived file and test by yourself here – Oo'- Jan 06 '19 at 21:47
  • @GustavoReis sorry, but I don't know what the issue is. You presented this as a text processing problem. If the script didn't do what it was supposed to do in terms of the text changed/inserted, then please explain how (preferably in a new question), but if it did what you asked for but that doesn't result in a valid svg file, I am afraid I can't help. I don't know how svg files work. – terdon Jan 06 '19 at 22:08
  • I found the solution and solved. I would like to credit you, but I ask for your authorisation to credit you in the files AUTHORS. – Oo'- Jan 07 '19 at 03:29
  • @GustavoReis that's not necessary, but thank you! You can simply link to this answer if you like. – terdon Jan 07 '19 at 08:57