C# 使用通配符在每次出现文本字符串后插入文本

C# insert text after each occurence of a text string using wildcards

已解决: 此解决方案已解决。我正在修改一个游戏并正在创建一个 C# windows 表单来轻松处理大量重复数据或表达式,并快速将大量更改插入一个或多个文件。我坚持在我的数据文件中使用 Regex 识别正则表达式,并在我识别的表达式之后立即插入数据文本框字段。感谢@Kris,我的表达式在正则表达式编辑器中有效,但是当我将它部署到我的程序中时,没有任何反应。很抱歉没有理清思路,下次使用 SO 时一定会更清楚。

下面是我想要操作的数据,后面是我能够使用@Kris 和@Rufus L 的指针修复自己的工作代码。同样,我需要搜索特定的数据字符串并插入一个新字符串在文件中每次出现的数据 属性 下方。希望这对某人有所帮助。

数据属性文本如下所示:

1234 = {
    workers = { 
        culture = dudes
        religion = awesome
        size = 37800
    }
    professionals = { 
        culture = dudes
        religion = awesome
        size = 6000
    }
    leaders = { 
        culture = dudes
        religion = awesome
        size = 500
    }
}
1235 = {
    workers = { 
        culture = dudes
        religion = awesome
        size = 37800
    }
    professionals = { 
        culture = dudes
        religion = awesome
        size = 6000
    }
    leaders = { 
        culture = dudes
        religion = awesome
        size = 500
    }
}

我只想将文本插入包含子字段 = {} 属性 的父字段 #### = {} 属性。 IE,我想在 1234 = {

下的新行中插入 textBox2.Text

感谢@Kris,我在 here 上链接了正则表达式。

namespace WindowsFormsApplication1 {
    public partial class Form1 : Form {
        static string[] files;
        static int curNum = 0;
        static string[] txtFiles;
        static string[] provinces;
        public Form1() {
                InitializeComponent();
        }
        private void button1_Click(object sender, EventArgs e) {
            System.IO.File.WriteAllText(pathText.Text + txtFiles[curNum], richTextBox1.Text);
        }
        private void prevButton_Click(object sender, EventArgs e) {
            if(curNum > 0)
            curNum--;
            richTextBox1.Text = System.IO.File.ReadAllText(pathText.Text + txtFiles[curNum]);
            filenameLabel.Text = txtFiles[curNum];
        }
        private void loadButton_Click(object sender, EventArgs e) {
            curNum = 0;
            txtFiles = GetFileNames(pathText.Text, "*.txt");
            richTextBox1.Text = System.IO.File.ReadAllText(pathText.Text + txtFiles[curNum]);
            filenameLabel.Text = txtFiles[curNum];
        }
        static string[] GetFileNames(string path, string filter) {
            files = Directory.GetFiles(path, filter);
            for (int i = 0; i < files.Length; i++)
                files[i] = Path.GetFileName(files[i]);
            return files;
        }
        private void nextButton_Click(object sender, EventArgs e) {
            if(curNum < txtFiles.Length)
            curNum++;
            richTextBox1.Text = System.IO.File.ReadAllText(pathText.Text + txtFiles[curNum]);
            filenameLabel.Text = txtFiles[curNum];
        }
        private void appendButton_Click(object sender, EventArgs e)
    {
        provinces = Regex.Matches(richTextBox1.Text, @"\d+(.*?){")
            .Cast<Match>()
            .Select(m => m.Value)
            .ToArray();
        for (int i = 0; i < provinces.Length; i++)
        {
            richTextBox1.Text = richTextBox1.Text.Replace(provinces[i], provinces[i] + System.Environment.NewLine + "    " + textBox2.Text);
        }
    }
    }
}

使用正则表达式

\d+(.*?){

tested here

另一种方法是在每个块的末尾插入文本,方法是搜索由 0 或更多空白字符分隔的两个 } 字符。这个正则表达式看起来像:

Regex.Matches(searchString, "}\s}");

在任何一种情况下,当插入字符串时,我们应该从 last 匹配开始(在字符串的末尾)并向后移动到开头,因为每次插入都会改变字符串长度,因此会影响我们要插入的索引。

例如:

/// <summary>
/// Returns a string with newText inserted into parentText
/// </summary>
/// <param name="newText">The new text to insert</param>
/// <param name="parentText">The parent text to insert into</param>
/// <returns>The parent string with the newText inserted</returns>
private string GetInsertedText(string newText, string parentText)
{
    var newParentText = parentText;
    var matches = Regex.Matches(newParentText, "}\s}");

    // Replace from the last occurrence, since each insert will 
    // change the length of our string and alter the insert location
    for(int index = matches.Count - 1; index >= 0; index--)
    {
        var match = matches[index];

        newParentText = newParentText.Substring(0, match.Index + 1) + 
            Environment.NewLine + newText +
            newParentText.Substring(match.Index + 1);
    }

    return newParentText;
}

您可能还想创建一个方法,在 textBox1.Text 的每一行的开头添加 4 个空格,以便在插入后具有适当的缩进。例如:

private string GetIndentedText(string originalText, string indentText = "    ")
{
    return $"{indentText}{originalText}".Replace("\n", $"\n{indentText}").TrimEnd();
}

它的用法类似于:

private void button1_Click(object sender, EventArgs e)
{
    // Check for any text requirements here (like it should contain
    // an open brace, an equals sign, end with a close brace, etc.)
    if (textBox1.Text.Length > 0)
    {
        // Insert the new (indented) text into our RichTextBox
        richTextBox1.Text = GetInsertedText(GetIndentedText(textBox1.Text), 
            richTextBox1.Text);

        // Clear the input textbox
        textBox1.Text = "";
    }
}