C # Regex: Como posso substituir fichas com cadeias de caracteres geradas em tempo de execução?
-
18-09-2019 - |
Pergunta
Dado o seguinte entrada e cordas regex:
const string inputString = "${Principal}*${Rate}*${Years}";
const string tokenMatchRegexString = @"\${([^}]+)}";
Como posso substituir cada token (ou seja, $ {principal}, $ {Taxa} e $ {} anos) com o valor de retorno da função meu 'ReplaceToken'?
private static string ReplaceToken(string tokenString)
{
switch (tokenString)
{
case "Principal":
return GetPrincipal();
case "Rate":
return GetRate();
case "Years":
return GetYears();
default:
throw new NotImplementedException(String.Format("A replacment for the token '{0}' has not been implemented.", tokenString));
}
}
private static string GetPrincipal()
{
throw new NotImplementedException();
}
private static string GetRate()
{
throw new NotImplementedException();
}
private static string GetYears()
{
throw new NotImplementedException();
}
Solução
Regex tem uma sobrecarga que leva um MatchEvaluator. A entrada é um jogo, e ele retorna um string. O valor do jogo, neste caso, seria de toda a forma, para que você possa criar um calço que extrai o valor (você já está capturando-o dentro de sua Regex) e adapta-se ao método que você postou.
Regex.Replace(inputString,
tokenMatchRegexString,
match => TokenReplacement(match.Groups[1].Value));
Outras dicas
Se você realmente só tem um pequeno número de tokens para substituir que você sabe antes do tempo, você pode usar string.Replace()
apenas para substituir as fichas uma a uma. Esta técnica simples pode trabalhar, mas tem desvantagens. Não é particularmente extensível, que pode resultar em (descartáveis) cordas intermediários, e também pode resultar em confundir código.
Se você espera ter muitos símbolos diferentes e têm regras de correspondência consistente, você poderia usar Regex.Replace()
que leva um delegado MatchEvaluator
- essencialmente função que aceita uma jogos de expressão regular e retorna uma string para substituir o jogo com. A vantagem de usar a sobrecarga Replace()
que leva um MatchEvaluator
é que ele ajuda a evitar a criação de cadeias de intermediários que são então utilizados apenas para substituir o próximo jogo. Também é bom para reutilizar built-in classes de .NET, em vez de rolar seus próprios.
Finalmente, se você tiver requisitos jogo / substituição realmente complexas, você pode usar bibliotecas como StringTemplate fazer expansões modelo e substituição de jogo mais complexo.
Aqui está um exemplo de como usar a chamada Regex.Replace()
:
const string inputString = "${Principal}*${Rate}*${Years}";
const string tokenMatchRegexString = @"\${([^}]+)}";
var rex = new Regex( tokenMatchRegexString );
MatchEvaluator matchEval = match => TokenReplacement( match.Groups[1].Value );
rex.Replace( inputString, matchEval );
Não reinventar a roda. Eu uso StringTemplate (o C # versão) ao fazer coisas como esta.