如何替换文本文件中以特定单词开头并以 C# 中的特殊字符结尾的字符串?

How to replace a string in a text file which starts with a specific word and ends with a special character in C#?

我正在开发一个应用程序,它通过读取和写入文本文件来管理生产过程。首先,它从文本文件中读取信息并将信息放入数据网格视图中,例如:

然后应该可以在更改单元格值时更新文本文件中的信息。

这是示例测试文件:

567,Eindhoven,IGT,21,Stripping_e=20/05/2020,Stripping_s=21/05/2020,Stripping_f=,Cleaning_e=23/05/2020,Cleaning_s=27/05/2020,Cleaning_f=28/05/2020,Paint_e=28/05/2020,Paint_s=28/05/2020,Paint_f=29/05/2020,Cabinet_e=29/05/2020,Cabinet_s=31/05/2020,Cabinet_f=,Table_e=,Table_s=,Table_f=05/06/2020,Stand_e=05/06/2020,Stand_s=08/06/2020,Stand_f=,Display_e=08/06/2020,Display_s=11/06/2020,Display_f=,UControls_e=15/06/2020,UControls_s=,UControls_f=,Test_e=19/06/2020,Test_s=,Test_f=20/06/2020,Prepack_e=21/06/2020,Prepack_s=22/06/2020,Prepack_f=,Endpack_e=27/06/2020,Endpack_s=28/06/2020,Endpack_f=,Release_e=30/06/2020,Release_s=,Release_f=,

我想做的基本上是用单元格中输入的新日期替换文件中存储的日期。例如,对于 Cleaning_e=23/05/2020, 我想检查字符串是否以 Cleaning_e= 开头并以 , 结尾将其替换为 Cleaning_e=12/09/2020, 即在单元格中输入新日期。

我当前的代码是:

private void ExportToTextFile(int selectedDate)
        {
            string filename = dataGridView1.Rows[clickedRow].Cells[0].Value.ToString();
           // TextWriter writer = new StreamWriter($"../../{filename}.txt");
            var text = new StringBuilder();

            foreach (string s in File.ReadAllLines($"../../{filename}.txt"))
            {
               /* if (clickedColumn == 3 && selectedDate == 0)
                    text.AppendLine(s.Replace("Stripping_e=", $"Stripping_e={dataGridView1.Rows[clickedRow].Cells[clickedColumn].Value.ToString()}"));
                else if (clickedColumn == 3 && selectedDate == 1)
                    text.AppendLine(s.Replace("Stripping_s=", $"Stripping_s={dataGridView1.Rows[clickedRow].Cells[clickedColumn].Value.ToString()}"));
                else if (clickedColumn == 3 && selectedDate == 2)
                    text.AppendLine(s.Replace("Stripping_f=", $"Stripping_f={dataGridView1.Rows[clickedRow].Cells[clickedColumn].Value.ToString()}"));
                else if (clickedColumn == 3 && selectedDate == 3)
                    text.AppendLine(s.Replace("Stripping_d=", $"Stripping_d={dataGridView1.Rows[clickedRow].Cells[clickedColumn].Value.ToString()}"));
                else */if (clickedColumn == 4 && selectedDate == 0)
                {
                    text.AppendLine(s.Replace("Cleaning_e=", $"Cleaning_e={dataGridView1.Rows[clickedRow].Cells[clickedColumn].Value.ToString()}"));
                    
                }/*
                else if (clickedColumn == 4 && selectedDate == 1)
                    text.AppendLine(s.Replace("Cleaning_s=", $"Cleaning_s={dataGridView1.Rows[clickedRow].Cells[clickedColumn].Value.ToString()}"));
                else if (clickedColumn == 4 && selectedDate == 2)
                    text.AppendLine(s.Replace("Cleaning_f=", $"Cleaning_f={dataGridView1.Rows[clickedRow].Cells[clickedColumn].Value.ToString()}"));
                else if (clickedColumn == 4 && selectedDate == 3)
                    text.AppendLine(s.Replace("Cleaning_d=", $"Cleaning_d={dataGridView1.Rows[clickedRow].Cells[clickedColumn].Value.ToString()}"));*/
            }
            using (var file = new StreamWriter(File.Create($"../../{filename}.txt")))
            {
                file.Write(text.ToString());
            }

        }

在我做了 text.AppendLine(s.Replace("Cleaning_e=",$"Cleaning_e={dataGridView1.Rows[clickedRow].Cells[clickedColumn].Value.ToString()}")); 之后,它写入了文件:Cleaning_e=12/09/202023/05/2020

如何确保在添加新日期之前删除输入的旧日期?

我尝试删除该字符串并写入已删除字符串的索引,但我无法使其工作。我也尝试过使用正则表达式,但没有成功。

提前致谢!

要用正则表达式替换它,您可以使用

var testText = "some other stuff Cleaning_e=12/43/4555, some more ";
var newValue = "78/65/0000";
var rx = new Regex(@"Cleaning_e=(\d\d/\d\d/\d\d\d\d)?");
var result = rx.Replace(testText, $"Cleaning_e={newValue}");

这将替换日期。请注意,这会替换 Cleaning_e 的每一次出现,并且要求日期格式恰好具有 2 2 和 4 位数字。如果位数不同,可以使用

var rx = new Regex(@"Cleaning_e=(\d+/\d+/\d+)?");

相反。

我宁愿建议将其解析为适当的结构并更改其中的值,而不是直接操作文本文件。

如果是我...我会首先通过打破命令中的所有字段来解析文件(使用 string.Split):

private const string SomeStuff =
    "567,Eindhoven,IGT,21,Stripping_e=20/05/2020,Stripping_s=21/05/2020,Stripping_f=,Cleaning_e=23/05/2020,Cleaning_s=27/05/2020,Cleaning_f=28/05/2020,Paint_e=28/05/2020,Paint_s=28/05/2020,Paint_f=29/05/2020,Cabinet_e=29/05/2020,Cabinet_s=31/05/2020,Cabinet_f=,Table_e=,Table_s=,Table_f=05/06/2020,Stand_e=05/06/2020,Stand_s=08/06/2020,Stand_f=,Display_e=08/06/2020,Display_s=11/06/2020,Display_f=,UControls_e=15/06/2020,UControls_s=,UControls_f=,Test_e=19/06/2020,Test_s=,Test_f=20/06/2020,Prepack_e=21/06/2020,Prepack_s=22/06/2020,Prepack_f=,Endpack_e=27/06/2020,Endpack_s=28/06/2020,Endpack_f=,Release_e=30/06/2020,Release_s=,Release_f=,";
var fields = SomeStuff.Split(new[]{','}, StringSplitOptions.None);

到那时,您将拥有一组字符串。然后我会创建一个如下所示的正则表达式:

private const string ParsePattern = @"(?<key>[a-zA-Z0-9_]+)=(?<date>\d{2}/\d{2}/\d{4})";
private static readonly Regex ParseRegex = new Regex(ParsePattern);

该正则表达式会查找任意数量的字母、数字或下划线,然后是“=”,然后是两位数字、一个斜线、另外两位数字、另一个斜线,最后是另外四位数字。等号前的“组”将被命名为“key”,等号后的日期将被命名为“date”。

最后,我将构建一个没有日期的字段列表和一个字典来保存 field-name/date 组合:

var noDateStrings = new List<string>();
var dateDictionary = new Dictionary<string, DateTime>();

在 had 中,我将遍历已解析的字符串集合。如果与正则表达式匹配,我会把这两个组件放入字典中。如果没有匹配项,那么我会将它们粘贴到我的不匹配项中 List<string>:

foreach (var field in fields)
{
    var patternMatches = ParseRegex.Matches(field);
    if (patternMatches.Count == 0)
    {
        noDateStrings.Add(field);
    }
    else
    {
        var groups = patternMatches[0].Groups;
        var date = DateTime.ParseExact(groups["date"].ToString(), "dd/mm/yyyy",
            CultureInfo.InvariantCulture);
        dateDictionary.Add(groups["key"].ToString(), date);
    }
}

这里有您需要的所有信息,可以为所欲为。

最后一件事要注意。我几乎总是主张在解析事物时使用 TryParse 而不是 Parse。但是,在这种情况下,我知道该字符串与日期模式相匹配。除非该字符串表示非法日期(例如 32/13/2020),否则它将正常解析。