Eu tenho uma variável de script de shell, que atualmente é definida assim:
tsource=/backup/%HOST%/%SHARE%/%PERIOD%
Eu quero combinar este modelo com outra variável, que pode ter um valor como este:
psource=/backup/somehost/someshare/monthly.1
Meu objetivo é gerar as seguintes atribuições para que eu possa usá-las para uma substituição posteriormente no script:
vars[HOST]=somehost
vars[SHARE]=someshare
vars[PERIOD]=monthly.1
Devo salientar que o usuário pode substituir esses dois valores e podemos acabar com formas diferentes (mas ainda correspondentes), o que significa que uma simples "divisão em /
" (ou mesmo "divisão na pontuação") é insuficiente:
tsource=/backup/%PERIOD/where/%HOST%-%SHARE%
psource=/backup/monthly.1/where/somehost-someshare
A intenção é poder analisar $psource
com base no modelo fornecido pelo $tsource
. Como é um software utilitário, eu realmente não me importo se o usuário tentar quebrá-lo - ele falhará mais tarde se parâmetros insuficientes ou inválidos forem fornecidos.
Olhando para possíveis soluções, acho que algo como sscanf
poderia ser útil aqui, que é uma ferramenta que está indiretamente disponível para mim. Eu posso facilmente manipular $tsource
para extrair HOST
, SHARE
e PERIOD
, e derivar um sscanf
modelo:
grep -Po "(?<=%)[[:upper:]]+(?=%)" <<<"$tsource" # "HOST" "SHARE" "PERIOD"
tscanf=$(sed -re 's/%[[:upper:]]+%/%s/g' <<<"$tsource") # "/backup/%s/%s/%s"
Isso me permitiria aplicar o modelo em Perl, como este exemplo:
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"
(Se eu fosse mergulhar no Perl, provavelmente faria a reescrita e sscanf
geração do modelo na parte do Perl também, mas vamos estacionar isso por enquanto.)
No entanto, é um pouco difícil escrever um script de shell que precisa do perl
.
Existe uma solução alternativa (melhor) que me permita mapear valores de uma string para rótulos bastante arbitrários em um modelo, que não envolva um mergulho rápido no Perl?
Usar expressões regulares é uma opção? Eu ainda tive que desembolsar para
sed
substituir de forma limpa%...%
, no(.*)
entanto:isso deve fazer o truque:
echo ${vars[HOST]} ${vars[SHARE]} ${vars[PERIOD]}
>
somehost someshare monthly.1