C# 替换字符串中的许多可变长度占位符

C# 替换字符串中的许多可变长度占位符,c#,replace,C#,Replace,晚上好, 我试图找到所有以“{”开头,以“}”结尾的字符串,然后用不同的字符串替换它们。为了帮助说明,下面是一个简短的示例 string exampleString = "My name is {Name}. I was born as {Race}. I am {Height} tall. My hair is {HairLength}."; 在上面的字符串中,我想删除{Name}、{Race}、{Height}和{HairLength},并用其他内容替换它们。我想,我现在在使用子字符串时遇

晚上好,

我试图找到所有以“{”开头,以“}”结尾的字符串,然后用不同的字符串替换它们。为了帮助说明,下面是一个简短的示例

string exampleString = "My name is {Name}. I was born as {Race}. I am {Height} tall. My hair is {HairLength}.";
在上面的字符串中,我想删除{Name}、{Race}、{Height}和{HairLength},并用其他内容替换它们。我想,我现在在使用子字符串时遇到了麻烦,因为我似乎无法在正确的位置拆分字符串,所以只能删除括号中的单词

我想我有点累了,犯了一些愚蠢的错误,但我现在看不到。下面是我用来分割字符串的(凌乱的)代码

public static string ForPlayer ( string originalString )
{

    string richText = originalString;

    PropertyInfo propertyInfo;
    int openingInstance = 0;
    int closingInstance = 0;

    int length = 0;
    foreach ( char c in originalString.ToCharArray ())
    {

        if ( c == '{' )
        {

            openingInstance = length;
        }

        if (  c == '}' && openingInstance > closingInstance )
        {

            int lastBrace = closingInstance;
            closingInstance = length;
            int lengthToNextBrace = originalString.IndexOf ( "{", closingInstance ) - closingInstance - 1;

            string richInstance = originalString.Substring ( openingInstance + 1, closingInstance - openingInstance - 1 );
            propertyInfo = Player.player.GetType ().GetProperty ( richInstance );
            if ( propertyInfo != null )
            {

                string beginning;
                string end;

                if ( lastBrace == 0 )
                {

                    beginning = originalString.Substring ( 0, openingInstance );
                } else
                {

                    beginning = originalString.Substring ( closingInstance + 1, openingInstance - lastBrace );
                }

                if ( lengthToNextBrace > -1 )
                {

                    end = originalString.Substring ( closingInstance + 1, lengthToNextBrace );
                } else
                {

                    end = originalString.Substring ( closingInstance + 1, originalString.Length - closingInstance - 1 );
                }

                richText = beginning + propertyInfo.GetValue ( Player.player, null ) + end;
                UnityEngine.Debug.Log ( beginning + propertyInfo.GetValue ( Player.player, null ) + end );
            }
        }

        length += 1;
    }

    return richText;
}
我得到:

DEBUG: "My name is default. I was born as "

DEBUG: ". I am {Height} tdefault. I am "

DEBUG: " tall. Mdefault tall. My hair is "

ERROR: "ArgumentOutOfRangeException: startIndex + length > this.length"
我想:

My name is defaultName. I was born as 

defaultRace. I am 

defaultHeight tall. My hair is 

defaultHairLength.
==编辑===

谢谢大家的回答!不幸的是,我不知道我要替换的字符串是什么,而且有太多的可能性,如果可能的话,我宁愿使用我目前通过反射找到它的方法。

var replacement=new Dictionary{
var replacement=new Dictionary<string,string>{
    {"Name","defaultName"},
    {"Race","defaultRace"},
    {"Height","defaultHeight"},
    {"HairLength","defaultHairLength"}
};
string exampleString="My name is {Name}. I was born as {Race}. I am {Height} tall. My hair is {HairLength}.";

foreach(var kv in replacement)
{
  exampleString = exampleString.Replace("{" + kv.Key + "}", kv.Value);
}
public static string ForPlayer(string originalString, object player)
{
    var type = player.GetType();
    var sb = new StringBuilder(originalString.Length);
    var lastEnd = 0;    // after the last close brace
    var start = originalString.IndexOf('{');    // start brace

    while (start != -1) // go until we run out of open braces
    {
        var end = originalString.IndexOf('}', start + 1);   // end brace
        if (end == -1)  // if there's a start brace but no end, just quit
            break;
        // copy from the end of the last string to the start of the new one
        sb.Append(originalString, lastEnd, start - lastEnd);
        // get the name of the property to look up
        var propName = originalString.Substring(start + 1, end - start - 1);
        // add in the property value
        sb.Append(type.GetProperty(propName).GetValue(player, null));
        lastEnd = end + 1;  // move the pointer to the end of the last string
        start = originalString.IndexOf('{', lastEnd);   // find the next start
    }

    // copy the end of the string
    sb.Append(originalString, lastEnd, originalString.Length - lastEnd);
    return sb.ToString();
}
{“Name”,“defaultName”}, {“种族”,“默认种族”}, {“高度”、“默认高度”}, {“HairLength”,“defaultHairLength”} }; string exampleString=“我的名字是{name}。我出生时是{Race}。我是{Height}高。我的头发是{HairLength}。”; foreach(替换中的var kv) { exampleString=exampleString.Replace(“{”+kv.Key+“}”,kv.Value); }

从PetSerAl中窃取第一部分,这里是我使用正则表达式的方法

using System.Text.RegularExpressions;
...
class Program
{
    static int occurence = 0;
    static string[] defValues = new string[] { "DefName", "DefRace", "DefHeight", "DefHair" };
    static string ReplaceWithDefault(Match m)
    {
        if (occurence < defValues.Length)
            return defValues[occurence++];
        else
            return "NO_DEFAULT_VALUE_FOUND";
    }

    static void Main(string[] args)
    {
        string exampleString = "My name is {Name}. I was born as {Race}. I am {Height} tall. My hair is {HairLength}.";
        string replaced = Regex.Replace(exampleString, "\\{[^\\}]+\\}", new MatchEvaluator(ReplaceWithDefault));
        occurence = 0;
        Console.WriteLine(exampleString);
        Console.WriteLine(replaced);
    }
}
使用System.Text.regular表达式;
...
班级计划
{
静态int发生率=0;
静态字符串[]defValues=新字符串[]{“DefName”、“DefRace”、“DefHeight”、“DefHair”};
静态字符串ReplaceWithDefault(匹配m)
{
if(发生时间
试试这个:

public static string ForPlayer(string originalString)
{
    return
        Regex
            .Matches(originalString, "{(.*?)}")
            .Cast<Match>()
            .Select(x => x.Groups[1].Value)
            .Select(x => new
            {
                From = x,
                To = Player.player
                    .GetType()
                    .GetProperty(x)
                    .GetValue(Player.player)
                    .ToString()
            })
            .Aggregate(originalString, (a, x) => a.Replace("{" + x.From + "}", x.To));
}
得到了这个结果:

"My name is Fred. I was born as English. I am Tall tall. My hair is 33."

这甚至更好:

public static string ForPlayer(string originalString)
{
    return
        Regex
            .Replace(originalString, "{(.*?)}", m =>
                Player.player
                    .GetType()
                    .GetProperty(m.Groups[1].Value)
                    .GetValue(Player.player)
                    .ToString());
}

如果占位符实际上是对象的属性名,那么您可以利用它来完成这项工作

string exampleString = "My name is {Name}. I was born as {Race}. I am {Height} tall. My hair is {HairLength}.";
string replacedString = exampleString.FormatWith(Player.player);

这是一个干净、简单的版本。它使用
IndexOf
方法查找大括号,而不是迭代字符。它还使用
StringBuilder
,尽可能避免复制字符串

public static string ForPlayer(string originalString, object player)
{
    var type = player.GetType();
    var sb = new StringBuilder(originalString.Length);
    var lastEnd = 0;    // after the last close brace
    var start = originalString.IndexOf('{');    // start brace

    while (start != -1) // go until we run out of open braces
    {
        var end = originalString.IndexOf('}', start + 1);   // end brace
        if (end == -1)  // if there's a start brace but no end, just quit
            break;
        // copy from the end of the last string to the start of the new one
        sb.Append(originalString, lastEnd, start - lastEnd);
        // get the name of the property to look up
        var propName = originalString.Substring(start + 1, end - start - 1);
        // add in the property value
        sb.Append(type.GetProperty(propName).GetValue(player, null));
        lastEnd = end + 1;  // move the pointer to the end of the last string
        start = originalString.IndexOf('{', lastEnd);   // find the next start
    }

    // copy the end of the string
    sb.Append(originalString, lastEnd, originalString.Length - lastEnd);
    return sb.ToString();
}

谢谢你的评论,pm100,但我认为这个方法行不通,因为我不知道字符串之前会是什么,而“defaultName”等只是占位符,因为“Name”是用来通过反射查找不同类上变量的名称的。所以只需在运行时加载字典,在需要之前,我不会知道这些键或值。谢谢你的回答!不幸的是,我无法为这些值创建数组或字典,但我很感谢您的建议!下次我会尽量把我的问题说得更清楚些,这样我就不会把这么多人搞糊涂了。神秘,谢谢你的回答!它解决了我的问题,但我不太理解RegEx(或者Linq),你能给我指出一个学习它的好起点吗,这样我就可以理解你的答案了?再次感谢@MichaelBethke-我的“更好”答案不使用linq。我使用的方法的
Regex.Replace
文档可以在这里找到:Gabe,感谢您花时间编写和评论,所有这些!regex解决方案是我在尝试上面发布的内容之前想要做的,但我想不出来。我认为这个答案是正确的,但我真的很感谢你的努力,并认识到这正是我所要求的。