2

I've got a SVG file of the map of the US and I want to add colors to it. Because it would take me to much time, I thought I could use a bash script. I have also another file containing the states and the colors that belong to them.

SVG-file:

<g id="hi">
    <title>Hawaii</title>
    <path class="state hi" d="m 233.08751,519.30948 ... z" id="HI" />
</g>

CSV-file

HI, blue

What I want:

<g id="hi" style="fill:blue;">
        <title>Hawaii</title>
        <path class="state hi" d="m 233.08751,519.30948 ... z" id="HI" />
    </g>

I thought I could use grep or sed but I really don't know where to begin.

Gilles 'SO- stop being evil'
  • 807,993
  • 194
  • 1,674
  • 2,175
M-Reda Daoudi
  • 145
  • 1
  • 1
  • 6

4 Answers4

3

Using bash and GNU sed:

while IFS=",$IFS" read id color
do
    sed -i "s/g id=\"${id,,}\"/& style=\"fill:$color;\"/g" file.svg
done <file.csv

After this is done, file.svg looks like:

<g id="hi" style="fill:blue;">
    <title>Hawaii</title>
    <path class="state hi" d="m 233.08751,519.30948 ... z" id="HI" />
</g>

How it works

  • while IFS=",$IFS" read id color; do

    This starts a while loop by reading the variables id and color. We add a comma to IFS so that the input is split on commas as well as whitespace.

  • sed -i "s/g id=\"${id,,}\"/& style=\"fill:$color;\"/g" file.svg

    This does an in-place update of file.svg. This uses bash to convert id to lower case: ${id,,}. It looks for the string g id="${id,,}" and replaces it with g id="${id,,} style="fill:$color;".

    Note: $id and $color are substituted directly into a sed command. You should do this only if you trust the source of the file.csv file.

  • done <file.csv

    This concludes the while loop and instructs it to read from file.csv.

BSD (OSX)

If you are on a BSD system, we need to make a slight change to the sed command:

while IFS=",$IFS" read id color
do
    sed -i "" "s/g id=\"${id,,}\"/& style=\"fill:$color;\"/g" file.svg
done <file.csv
John1024
  • 73,527
  • 11
  • 167
  • 163
  • but the shell gives me this error: sed: -e expression #1, char 30: unterminated `s' command – M-Reda Daoudi Nov 29 '15 at 21:27
  • That would indicate a missing final `/`. Try copying-and-pasting again to make sure that the command is correct. Also, are you using the same `file.csv` in the question or a different one? If a different one, let me see the contents. – John1024 Nov 29 '15 at 21:32
2

Using Perl and its xsh :

perl {
    open my $FH, '<', 'states.csv' or die $!;
    $h->{lc $1} = "$2;" while <$FH> =~ /(.*),\s*(.*)/;
};

open map.xml ;
for //g set @style concat("fill:", xsh:lookup('h', @id));
save :b ;
choroba
  • 45,735
  • 7
  • 84
  • 110
1

using sed, twice:

</tmp/states.csv tr "[A-Z]" "[a-z]" | \
sed -n 's/^\([a-z]\{2\}\), \([^ ]*\)$/s@<g id="\1">@<g id="\1" style="fill:\2;">@/p' >/tmp/script.sed
sed -f /tmp/script.sed /tmp/source.svg

The first line creates a sed script (/tmp/script.sed) and the second line implements it. Assumes that your list of states is saved at /tmp/states.csv and your svg file at /tmp/source.svg.

gogoud
  • 2,613
  • 2
  • 14
  • 18
  • @mikeserv, OP has told us what is in the csv, It could be modified to work if there is other stuff in the csv. – gogoud Nov 30 '15 at 07:05
0
tr   \[:upper:] \[:lower:] <csv.file | sort -bt, -uk1,1   |
sed  -e'\|^ *\([[:alpha:]]\{2\}\) *, *\([[:alpha:]]\{1,\}\) *$|!d' \
     -e's||s/\\(<g id="\1"\\)>/\\1 style="fill:\2;">/;t|' |
sed  -f- svg.file
mikeserv
  • 57,448
  • 9
  • 113
  • 229