I've got a shell script variable, which currently is defined like this:
tsource=/backup/%HOST%/%SHARE%/%PERIOD%
I want to match this template to another variable, which might have a value like this:
psource=/backup/somehost/someshare/monthly.1
My aim is to generate the following assignments so that I can use them for a substitution later in the script:
vars[HOST]=somehost
vars[SHARE]=someshare
vars[PERIOD]=monthly.1
I should point out that the user can override both these values and we might end up with different (but still matching) shapes, which means that a simple "split at /" (or even "split at punctuation") is insufficient:
tsource=/backup/%PERIOD/where/%HOST%-%SHARE%
psource=/backup/monthly.1/where/somehost-someshare
The intention is to be able to parse $psource based on the template provided by $tsource. As it's utility software I don't really care if the user tries to break it - it'll bail at a later point if insufficient or invalid parameters have been provided.
Looking at possible solutions I think something like sscanf could be useful here, which is a tool that's indirectly available to me. I can easily enough manipulate $tsource to extract HOST, SHARE, and PERIOD, and derive a sscanf template:
grep -Po "(?<=%)[[:upper:]]+(?=%)" <<<"$tsource" # "HOST" "SHARE" "PERIOD"
tscanf=$(sed -re 's/%[[:upper:]]+%/%s/g' <<<"$tsource") # "/backup/%s/%s/%s"
This would allow me to apply the template in Perl, like this example:
perl -MString::Scanf -e '
$psource = "/backup/somehost/someshare/monthly.1";
$tscanf = "/backup/%s/%s/%s";
($host, $source, $period) = sscanf($tscanf, $psource);
print "host=$host, share=$share, period=$period\n"
'
# "host=somehost, share=someshare, period=monthly.1"
(If I was going to dive into Perl I'd probably do the template rewriting and sscanf generation in the Perl part too, but let's park that for now.)
However, it grates somewhat writing a shell script that needs perl.
Is there an alternative (better) solution that allows me to map values from a string for fairly arbitrary labels in a template, that doesn't involve a quick dive into Perl?
IFS='/' read -ra vars <<< $(echo ${psource#/*/})?; this'll give you your values in the arrayvars:vars[0]would be:somehost, and so on