I'm trying to write a bash script that will change the fill
color of certain elements within SVG files. I'm inexperienced with shell scripting, but I'm good with regexes (...in JS).
Here's the SVG tag I want to modify:
<!-- is the target because its ID is exactly "the.target" -->
<path id="the.target" d="..." style="fill:#000000" />
Here's the bash code I've got so far:
local newSvg="" # will hold newly-written SVG file content
while IFS="<$IFS" read tag
do
if [[ "${tag}" =~ +id *= *"the\.target" ]]; then
tag=$(echo "${tag}" | sed 's/fill:[^;];/fill:${color};/')
fi
newSvg="${newSvg}${tag}"
done < ${iconSvgPath} # is an argument to the script
Explained: I'm using read
(splitting the file on <
via custom IFS
) to read the SVG content tag by tag. For each tag, I test to see if it includes an id
property with the exact value I want. If it doesn't, I add this tag as-is to a newSvg
string that I will later write to a file. If the tag does have the desired ID, I'll used sed
to replace fill:STUFF;
with fill:${myColor};
. (Note that my sed
is also failing, but that's not what I'm asking about here.)
It fails to find the right line with the test [[ "${tag}" =~ +id *= *"the\.target" ]]
.
It succeeds if I change the test to [[ "${tag}" =~ \"the\.target\" ]]
.
I'm not happy with the working version because it's too brittle. While I don't intend to support all the flexibility of XML, I would like to be tolerant of semantically irrelevant whitespace, as well as the id property being anywhere within the tag. Ideally, the regex I'd like to write would express:
id
(preceded by at least one whitespace)- followed by zero or more whitespaces
- followed by
=
- followed by zero or more whitespaces
- followed by
"the.target"
I think I'm not delimiting the regex properly inside the [[ ... =~ REGEX ]]
construction, but none of the answers I've seen online use any delimiters whatsoever. In javascript, regex literals are bounded (e.g. / +id *= *"the\.target"/
), so it's straightforward beginning a regex with a whitespace character that you care about. Also, JS doesn't have any magic re: *
, whereas bash is 50% magic-handling-of-asterisks.
Any help is appreciated. My backup plan is maybe to try to use awk
instead (which I'm no better at).
EDIT: My sed was really close. I forgot to add +
after the [^;]
set. Oof.