Skip to content

C# 字符串处理

本章将详细介绍 C# 中的字符串处理,包括字符串的创建、操作、格式化、正则表达式等,帮助你掌握文本处理的各种技巧。

字符串基础

字符串的特性

csharp
// 字符串是不可变的(Immutable)
string str1 = "Hello";
string str2 = str1;
str1 += " World";  // 创建新字符串,str1 指向新对象

Console.WriteLine($"str1: {str1}");  // "Hello World"
Console.WriteLine($"str2: {str2}");  // "Hello" (未改变)

// 字符串是引用类型
string a = "test";
string b = "test";
Console.WriteLine($"a == b: {a == b}");           // True (值相等)
Console.WriteLine($"ReferenceEquals(a, b): {ReferenceEquals(a, b)}");  // True (字符串驻留)

// 字符串长度
string message = "Hello, C#!";
Console.WriteLine($"字符串长度: {message.Length}");

// 访问字符
Console.WriteLine($"第一个字符: {message[0]}");      // 'H'
Console.WriteLine($"最后一个字符: {message[message.Length - 1]}");  // '!'

字符串创建方式

csharp
// 1. 字符串字面量
string literal = "Hello World";

// 2. 逐字字符串(Verbatim String)
string path = @"C:\Users\Name\Documents\file.txt";
string multiline = @"这是一个
多行字符串
示例";

// 3. 字符串插值(String Interpolation)
string name = "Alice";
int age = 25;
string interpolated = $"姓名: {name}, 年龄: {age}";

// 4. 从字符数组创建
char[] chars = {'H', 'e', 'l', 'l', 'o'};
string fromChars = new string(chars);

// 5. 重复字符
string repeated = new string('*', 10);  // "**********"

// 6. 原始字符串字面量(C# 11+)
string raw = """
    这是原始字符串
    可以包含 "引号" 和 \反斜杠
    """;

Console.WriteLine($"字面量: {literal}");
Console.WriteLine($"路径: {path}");
Console.WriteLine($"多行:\n{multiline}");
Console.WriteLine($"插值: {interpolated}");
Console.WriteLine($"字符数组: {fromChars}");
Console.WriteLine($"重复字符: {repeated}");

字符串操作方法

基本操作

csharp
string text = "  Hello, C# Programming!  ";

// 长度和空值检查
Console.WriteLine($"长度: {text.Length}");
Console.WriteLine($"是否为空: {string.IsNullOrEmpty(text)}");
Console.WriteLine($"是否为空或空白: {string.IsNullOrWhiteSpace(text)}");

// 去除空白字符
Console.WriteLine($"原始: '{text}'");
Console.WriteLine($"去除两端空白: '{text.Trim()}'");
Console.WriteLine($"去除左侧空白: '{text.TrimStart()}'");
Console.WriteLine($"去除右侧空白: '{text.TrimEnd()}'");

// 大小写转换
Console.WriteLine($"转大写: {text.ToUpper()}");
Console.WriteLine($"转小写: {text.ToLower()}");
Console.WriteLine($"首字母大写: {text.Trim().ToLower()}");

// 子字符串
string sample = "Hello, World!";
Console.WriteLine($"子字符串(7): '{sample.Substring(7)}'");        // "World!"
Console.WriteLine($"子字符串(7,5): '{sample.Substring(7, 5)}'");    // "World"

// 字符串连接
string first = "Hello";
string second = "World";
Console.WriteLine($"连接: {first + " " + second}");
Console.WriteLine($"Concat: {string.Concat(first, " ", second)}");
Console.WriteLine($"Join: {string.Join(" ", first, second)}");

查找和替换

csharp
string text = "The quick brown fox jumps over the lazy dog";

// 查找字符和子字符串
Console.WriteLine($"包含 'fox': {text.Contains("fox")}");
Console.WriteLine($"以 'The' 开头: {text.StartsWith("The")}");
Console.WriteLine($"以 'dog' 结尾: {text.EndsWith("dog")}");

// 查找位置
int index = text.IndexOf("fox");
Console.WriteLine($"'fox' 的位置: {index}");

int lastIndex = text.LastIndexOf("the");
Console.WriteLine($"最后一个 'the' 的位置: {lastIndex}");

// 查找任意字符
int anyIndex = text.IndexOfAny(new char[] {'a', 'e', 'i', 'o', 'u'});
Console.WriteLine($"第一个元音字母位置: {anyIndex}");

// 替换
string replaced = text.Replace("fox", "cat");
Console.WriteLine($"替换后: {replaced}");

string removedSpaces = text.Replace(" ", "");
Console.WriteLine($"移除空格: {removedSpaces}");

// 大小写不敏感的操作
bool containsIgnoreCase = text.Contains("FOX", StringComparison.OrdinalIgnoreCase);
Console.WriteLine($"忽略大小写包含 'FOX': {containsIgnoreCase}");

字符串分割和连接

csharp
// 分割字符串
string csv = "apple,banana,orange,grape";
string[] fruits = csv.Split(',');
Console.WriteLine("水果列表:");
foreach (string fruit in fruits)
{
    Console.WriteLine($"- {fruit}");
}

// 多个分隔符分割
string text = "apple;banana,orange:grape";
string[] parts = text.Split(new char[] {',', ';', ':'});
Console.WriteLine($"分割结果: [{string.Join(", ", parts)}]");

// 限制分割数量
string data = "name=John;age=25;city=New York;country=USA";
string[] limited = data.Split(';', 3);
Console.WriteLine($"限制分割: [{string.Join(" | ", limited)}]");

// 移除空项
string withEmpty = "a,,b,c,";
string[] withoutEmpty = withEmpty.Split(',', StringSplitOptions.RemoveEmptyEntries);
Console.WriteLine($"移除空项: [{string.Join(", ", withoutEmpty)}]");

// 连接字符串数组
string[] words = {"Hello", "beautiful", "world"};
string joined = string.Join(" ", words);
Console.WriteLine($"连接结果: {joined}");

// 使用不同分隔符连接
string csvResult = string.Join(", ", words);
Console.WriteLine($"CSV 格式: {csvResult}");

字符串格式化

复合格式化

csharp
// 基本格式化
string name = "Alice";
int age = 25;
double salary = 5000.50;

// 位置参数
string formatted1 = string.Format("姓名: {0}, 年龄: {1}, 薪资: {2}", name, age, salary);
Console.WriteLine(formatted1);

// 格式说明符
Console.WriteLine($"货币格式: {salary:C}");           // ¥5,000.50
Console.WriteLine($"百分比格式: {0.85:P}");           // 85.00%
Console.WriteLine($"固定小数点: {salary:F2}");        // 5000.50
Console.WriteLine($"数字格式: {12345:N}");            // 12,345
Console.WriteLine($"十六进制: {255:X}");              // FF

// 日期时间格式化
DateTime now = DateTime.Now;
Console.WriteLine($"完整日期时间: {now:F}");
Console.WriteLine($"短日期: {now:d}");
Console.WriteLine($"长日期: {now:D}");
Console.WriteLine($"时间: {now:T}");
Console.WriteLine($"自定义格式: {now:yyyy-MM-dd HH:mm:ss}");

// 对齐和填充
Console.WriteLine($"左对齐: |{name,-10}|");
Console.WriteLine($"右对齐: |{name,10}|");
Console.WriteLine($"数字对齐: |{age,5}|{salary,10:F2}|");

字符串插值高级用法

csharp
// 基本插值
string name = "Bob";
int score = 95;
Console.WriteLine($"学生 {name} 的分数是 {score}");

// 表达式插值
Console.WriteLine($"分数等级: {(score >= 90 ? "A" : score >= 80 ? "B" : "C")}");

// 格式化插值
double price = 123.456;
Console.WriteLine($"价格: {price:C2}");
Console.WriteLine($"百分比: {0.1234:P1}");

// 对齐插值
Console.WriteLine($"|{name,-15}|{score,5}|");

// 转义大括号
Console.WriteLine($"显示大括号: {{这里是内容}}");

// 多行插值
string multilineInterpolation = $@"
学生信息:
  姓名: {name}
  分数: {score}
  等级: {(score >= 90 ? "优秀" : "良好")}
";
Console.WriteLine(multilineInterpolation);

// 条件插值
bool showDetails = true;
Console.WriteLine($"基本信息: {name}{(showDetails ? $" (分数: {score})" : "")}");

自定义格式化

csharp
// 实现 IFormattable 接口
public class Student : IFormattable
{
    public string Name { get; set; }
    public int Age { get; set; }
    public double GPA { get; set; }
    
    public Student(string name, int age, double gpa)
    {
        Name = name;
        Age = age;
        GPA = gpa;
    }
    
    public string ToString(string format, IFormatProvider formatProvider)
    {
        if (string.IsNullOrEmpty(format)) format = "G";
        
        return format.ToUpperInvariant() switch
        {
            "G" => $"{Name} ({Age}岁)",
            "F" => $"姓名: {Name}, 年龄: {Age}, GPA: {GPA:F2}",
            "S" => Name,
            "A" => Age.ToString(),
            "GPA" => GPA.ToString("F2"),
            _ => throw new FormatException($"格式 '{format}' 不受支持")
        };
    }
    
    public override string ToString() => ToString("G", null);
}

// 使用自定义格式化
static void CustomFormattingDemo()
{
    var student = new Student("Charlie", 20, 3.75);
    
    Console.WriteLine($"默认格式: {student}");
    Console.WriteLine($"完整格式: {student:F}");
    Console.WriteLine($"仅姓名: {student:S}");
    Console.WriteLine($"仅年龄: {student:A}");
    Console.WriteLine($"仅GPA: {student:GPA}");
}

StringBuilder 类

基本用法

csharp
using System.Text;

// StringBuilder 用于高效的字符串构建
StringBuilder sb = new StringBuilder();

// 添加内容
sb.Append("Hello");
sb.Append(" ");
sb.Append("World");
sb.AppendLine("!");  // 添加并换行

// 插入内容
sb.Insert(5, " Beautiful");

// 替换内容
sb.Replace("World", "C#");

Console.WriteLine($"StringBuilder 结果: {sb.ToString()}");
Console.WriteLine($"长度: {sb.Length}");
Console.WriteLine($"容量: {sb.Capacity}");

// 清空内容
sb.Clear();
Console.WriteLine($"清空后长度: {sb.Length}");

性能比较

csharp
using System.Diagnostics;

static void StringPerformanceComparison()
{
    const int iterations = 10000;
    var stopwatch = new Stopwatch();
    
    // 使用字符串连接
    stopwatch.Start();
    string result1 = "";
    for (int i = 0; i < iterations; i++)
    {
        result1 += "a";
    }
    stopwatch.Stop();
    Console.WriteLine($"字符串连接耗时: {stopwatch.ElapsedMilliseconds} ms");
    
    // 使用 StringBuilder
    stopwatch.Restart();
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < iterations; i++)
    {
        sb.Append("a");
    }
    string result2 = sb.ToString();
    stopwatch.Stop();
    Console.WriteLine($"StringBuilder 耗时: {stopwatch.ElapsedMilliseconds} ms");
    
    // 预设容量的 StringBuilder
    stopwatch.Restart();
    StringBuilder sbWithCapacity = new StringBuilder(iterations);
    for (int i = 0; i < iterations; i++)
    {
        sbWithCapacity.Append("a");
    }
    string result3 = sbWithCapacity.ToString();
    stopwatch.Stop();
    Console.WriteLine($"预设容量 StringBuilder 耗时: {stopwatch.ElapsedMilliseconds} ms");
}

StringBuilder 高级用法

csharp
using System.Text;

static void StringBuilderAdvanced()
{
    // 创建带初始容量的 StringBuilder
    StringBuilder sb = new StringBuilder(100);
    
    // 链式调用
    sb.Append("姓名: ")
      .Append("Alice")
      .AppendLine()
      .Append("年龄: ")
      .Append(25)
      .AppendLine()
      .Append("城市: ")
      .Append("北京");
    
    Console.WriteLine("链式调用结果:");
    Console.WriteLine(sb.ToString());
    
    // 格式化添加
    sb.Clear();
    sb.AppendFormat("今天是 {0:yyyy年MM月dd日}", DateTime.Now);
    sb.AppendLine();
    sb.AppendFormat("温度: {0:F1}°C", 25.6);
    
    Console.WriteLine("\n格式化结果:");
    Console.WriteLine(sb.ToString());
    
    // 移除字符
    sb.Remove(0, 3);  // 移除前3个字符
    Console.WriteLine($"\n移除前3个字符: {sb.ToString()}");
    
    // 设置长度
    sb.Length = 10;   // 截断到10个字符
    Console.WriteLine($"截断到10个字符: {sb.ToString()}");
}

正则表达式

基本正则表达式

csharp
using System.Text.RegularExpressions;

static void BasicRegexDemo()
{
    string text = "联系电话: 138-1234-5678, 邮箱: user@example.com";
    
    // 匹配手机号码
    string phonePattern = @"\d{3}-\d{4}-\d{4}";
    Match phoneMatch = Regex.Match(text, phonePattern);
    if (phoneMatch.Success)
    {
        Console.WriteLine($"找到手机号: {phoneMatch.Value}");
    }
    
    // 匹配邮箱地址
    string emailPattern = @"\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z|a-z]{2,}\b";
    Match emailMatch = Regex.Match(text, emailPattern);
    if (emailMatch.Success)
    {
        Console.WriteLine($"找到邮箱: {emailMatch.Value}");
    }
    
    // 查找所有数字
    string numberPattern = @"\d+";
    MatchCollection numberMatches = Regex.Matches(text, numberPattern);
    Console.WriteLine("找到的数字:");
    foreach (Match match in numberMatches)
    {
        Console.WriteLine($"- {match.Value}");
    }
    
    // 验证格式
    string[] emails = {
        "valid@example.com",
        "invalid.email",
        "another@test.org",
        "bad@email"
    };
    
    Console.WriteLine("\n邮箱验证:");
    foreach (string email in emails)
    {
        bool isValid = Regex.IsMatch(email, emailPattern);
        Console.WriteLine($"{email}: {(isValid ? "有效" : "无效")}");
    }
}

正则表达式替换和分组

csharp
using System.Text.RegularExpressions;

static void RegexReplaceAndGroups()
{
    // 替换操作
    string text = "今天的日期是 2023-12-25,明天是 2023-12-26";
    
    // 简单替换
    string replaced = Regex.Replace(text, @"\d{4}-\d{2}-\d{2}", "YYYY-MM-DD");
    Console.WriteLine($"替换日期: {replaced}");
    
    // 使用分组进行复杂替换
    string datePattern = @"(\d{4})-(\d{2})-(\d{2})";
    string dateReplaced = Regex.Replace(text, datePattern, "$3/$2/$1");
    Console.WriteLine($"日期格式转换: {dateReplaced}");
    
    // 分组捕获
    string logEntry = "2023-12-25 14:30:15 [ERROR] 数据库连接失败";
    string logPattern = @"(\d{4}-\d{2}-\d{2}) (\d{2}:\d{2}:\d{2}) \[(\w+)\] (.+)";
    
    Match logMatch = Regex.Match(logEntry, logPattern);
    if (logMatch.Success)
    {
        Console.WriteLine("\n日志解析:");
        Console.WriteLine($"日期: {logMatch.Groups[1].Value}");
        Console.WriteLine($"时间: {logMatch.Groups[2].Value}");
        Console.WriteLine($"级别: {logMatch.Groups[3].Value}");
        Console.WriteLine($"消息: {logMatch.Groups[4].Value}");
    }
    
    // 命名分组
    string namedPattern = @"(?<date>\d{4}-\d{2}-\d{2}) (?<time>\d{2}:\d{2}:\d{2}) \[(?<level>\w+)\] (?<message>.+)";
    Match namedMatch = Regex.Match(logEntry, namedPattern);
    if (namedMatch.Success)
    {
        Console.WriteLine("\n命名分组解析:");
        Console.WriteLine($"日期: {namedMatch.Groups["date"].Value}");
        Console.WriteLine($"时间: {namedMatch.Groups["time"].Value}");
        Console.WriteLine($"级别: {namedMatch.Groups["level"].Value}");
        Console.WriteLine($"消息: {namedMatch.Groups["message"].Value}");
    }
}

常用正则表达式模式

csharp
using System.Text.RegularExpressions;

static class RegexPatterns
{
    // 常用正则表达式模式
    public static readonly string Email = @"^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$";
    public static readonly string Phone = @"^1[3-9]\d{9}$";  // 中国手机号
    public static readonly string IdCard = @"^\d{17}[\dXx]$";  // 身份证号
    public static readonly string Url = @"^https?://[^\s/$.?#].[^\s]*$";
    public static readonly string IPv4 = @"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$";
    public static readonly string Password = @"^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]{8,}$";
    
    public static bool ValidateEmail(string email)
    {
        return Regex.IsMatch(email, Email);
    }
    
    public static bool ValidatePhone(string phone)
    {
        return Regex.IsMatch(phone, Phone);
    }
    
    public static bool ValidatePassword(string password)
    {
        return Regex.IsMatch(password, Password);
    }
    
    public static string ExtractNumbers(string text)
    {
        return Regex.Replace(text, @"[^\d]", "");
    }
    
    public static string[] SplitByWhitespace(string text)
    {
        return Regex.Split(text, @"\s+");
    }
}

static void ValidationDemo()
{
    Console.WriteLine("=== 数据验证演示 ===");
    
    // 邮箱验证
    string[] emails = {
        "user@example.com",
        "invalid.email",
        "test@domain.co.uk",
        "bad@"
    };
    
    Console.WriteLine("邮箱验证:");
    foreach (string email in emails)
    {
        bool isValid = RegexPatterns.ValidateEmail(email);
        Console.WriteLine($"{email}: {(isValid ? "✓" : "✗")}");
    }
    
    // 手机号验证
    string[] phones = {
        "13812345678",
        "12345678901",
        "15987654321",
        "1234567890"
    };
    
    Console.WriteLine("\n手机号验证:");
    foreach (string phone in phones)
    {
        bool isValid = RegexPatterns.ValidatePhone(phone);
        Console.WriteLine($"{phone}: {(isValid ? "✓" : "✗")}");
    }
    
    // 密码强度验证
    string[] passwords = {
        "Password123!",
        "password",
        "PASSWORD123",
        "Pass123",
        "MySecure@Pass1"
    };
    
    Console.WriteLine("\n密码强度验证 (需要大小写字母、数字、特殊字符,至少8位):");
    foreach (string password in passwords)
    {
        bool isValid = RegexPatterns.ValidatePassword(password);
        Console.WriteLine($"{password}: {(isValid ? "✓" : "✗")}");
    }
}

实践示例

示例 1:文本分析工具

csharp
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.RegularExpressions;

class TextAnalyzer
{
    public class AnalysisResult
    {
        public int CharacterCount { get; set; }
        public int WordCount { get; set; }
        public int SentenceCount { get; set; }
        public int ParagraphCount { get; set; }
        public Dictionary<string, int> WordFrequency { get; set; }
        public double AverageWordsPerSentence { get; set; }
        public string MostFrequentWord { get; set; }
    }
    
    public static AnalysisResult AnalyzeText(string text)
    {
        if (string.IsNullOrWhiteSpace(text))
            return new AnalysisResult();
        
        var result = new AnalysisResult();
        
        // 字符数(不包括空白字符)
        result.CharacterCount = text.Count(c => !char.IsWhiteSpace(c));
        
        // 单词数
        string[] words = Regex.Split(text.ToLower(), @"\W+")
                             .Where(w => !string.IsNullOrEmpty(w))
                             .ToArray();
        result.WordCount = words.Length;
        
        // 句子数
        result.SentenceCount = Regex.Matches(text, @"[.!?]+").Count;
        
        // 段落数
        result.ParagraphCount = text.Split(new string[] { "\n\n", "\r\n\r\n" }, 
                                         StringSplitOptions.RemoveEmptyEntries).Length;
        
        // 词频统计
        result.WordFrequency = words.GroupBy(w => w)
                                   .ToDictionary(g => g.Key, g => g.Count());
        
        // 平均每句话的单词数
        result.AverageWordsPerSentence = result.SentenceCount > 0 
            ? (double)result.WordCount / result.SentenceCount 
            : 0;
        
        // 最频繁的单词
        result.MostFrequentWord = result.WordFrequency.Any() 
            ? result.WordFrequency.OrderByDescending(kvp => kvp.Value).First().Key 
            : "";
        
        return result;
    }
    
    public static void DisplayAnalysis(AnalysisResult result)
    {
        Console.WriteLine("=== 文本分析结果 ===");
        Console.WriteLine($"字符数: {result.CharacterCount}");
        Console.WriteLine($"单词数: {result.WordCount}");
        Console.WriteLine($"句子数: {result.SentenceCount}");
        Console.WriteLine($"段落数: {result.ParagraphCount}");
        Console.WriteLine($"平均每句单词数: {result.AverageWordsPerSentence:F1}");
        Console.WriteLine($"最频繁单词: {result.MostFrequentWord}");
        
        Console.WriteLine("\n词频统计 (前10个):");
        var topWords = result.WordFrequency
                            .OrderByDescending(kvp => kvp.Value)
                            .Take(10);
        
        foreach (var word in topWords)
        {
            Console.WriteLine($"  {word.Key}: {word.Value}次");
        }
    }
    
    static void Main()
    {
        string sampleText = @"
        C# 是一种现代的、通用的、面向对象的编程语言。
        它由微软开发,是 .NET 平台的主要语言之一。
        C# 语言简洁、类型安全、面向对象。
        
        C# 广泛应用于桌面应用、Web 开发、移动应用等领域。
        学习 C# 可以帮助开发者构建各种类型的应用程序。
        ";
        
        var result = AnalyzeText(sampleText);
        DisplayAnalysis(result);
    }
}

示例 2:日志解析器

csharp
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using System.Linq;

class LogEntry
{
    public DateTime Timestamp { get; set; }
    public string Level { get; set; }
    public string Source { get; set; }
    public string Message { get; set; }
    
    public override string ToString()
    {
        return $"[{Timestamp:yyyy-MM-dd HH:mm:ss}] {Level} - {Source}: {Message}";
    }
}

class LogParser
{
    private static readonly Regex LogPattern = new Regex(
        @"(?<timestamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\s+\[(?<level>\w+)\]\s+(?<source>\w+):\s*(?<message>.*)",
        RegexOptions.Compiled);
    
    public static List<LogEntry> ParseLogs(string[] logLines)
    {
        var entries = new List<LogEntry>();
        
        foreach (string line in logLines)
        {
            if (string.IsNullOrWhiteSpace(line))
                continue;
                
            var match = LogPattern.Match(line);
            if (match.Success)
            {
                var entry = new LogEntry
                {
                    Timestamp = DateTime.Parse(match.Groups["timestamp"].Value),
                    Level = match.Groups["level"].Value,
                    Source = match.Groups["source"].Value,
                    Message = match.Groups["message"].Value
                };
                entries.Add(entry);
            }
        }
        
        return entries;
    }
    
    public static void AnalyzeLogs(List<LogEntry> entries)
    {
        Console.WriteLine("=== 日志分析 ===");
        Console.WriteLine($"总日志条数: {entries.Count}");
        
        // 按级别统计
        var levelStats = entries.GroupBy(e => e.Level)
                               .ToDictionary(g => g.Key, g => g.Count());
        
        Console.WriteLine("\n按级别统计:");
        foreach (var stat in levelStats.OrderByDescending(kvp => kvp.Value))
        {
            Console.WriteLine($"  {stat.Key}: {stat.Value} 条");
        }
        
        // 按来源统计
        var sourceStats = entries.GroupBy(e => e.Source)
                                .ToDictionary(g => g.Key, g => g.Count());
        
        Console.WriteLine("\n按来源统计:");
        foreach (var stat in sourceStats.OrderByDescending(kvp => kvp.Value))
        {
            Console.WriteLine($"  {stat.Key}: {stat.Value} 条");
        }
        
        // 错误日志
        var errors = entries.Where(e => e.Level.Equals("ERROR", StringComparison.OrdinalIgnoreCase))
                           .ToList();
        
        if (errors.Any())
        {
            Console.WriteLine($"\n错误日志 ({errors.Count} 条):");
            foreach (var error in errors.Take(5))  // 显示前5条
            {
                Console.WriteLine($"  {error}");
            }
        }
        
        // 时间范围
        if (entries.Any())
        {
            var earliest = entries.Min(e => e.Timestamp);
            var latest = entries.Max(e => e.Timestamp);
            Console.WriteLine($"\n时间范围: {earliest:yyyy-MM-dd HH:mm:ss} 到 {latest:yyyy-MM-dd HH:mm:ss}");
        }
    }
    
    static void Main()
    {
        string[] sampleLogs = {
            "2023-12-25 10:30:15 [INFO] Application: 系统启动成功",
            "2023-12-25 10:30:16 [DEBUG] Database: 连接数据库",
            "2023-12-25 10:30:17 [INFO] Authentication: 用户登录成功",
            "2023-12-25 10:35:22 [WARN] Cache: 缓存命中率较低",
            "2023-12-25 10:40:33 [ERROR] Database: 数据库连接超时",
            "2023-12-25 10:41:15 [INFO] Application: 重新连接数据库",
            "2023-12-25 10:42:00 [ERROR] Payment: 支付处理失败",
            "2023-12-25 10:45:30 [INFO] Cleanup: 清理临时文件完成"
        };
        
        var entries = ParseLogs(sampleLogs);
        AnalyzeLogs(entries);
    }
}

示例 3:模板引擎

csharp
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;

class SimpleTemplateEngine
{
    private static readonly Regex VariablePattern = new Regex(
        @"\{\{(\w+)\}\}", 
        RegexOptions.Compiled);
    
    private static readonly Regex LoopPattern = new Regex(
        @"\{\{\s*for\s+(\w+)\s+in\s+(\w+)\s*\}\}(.*?)\{\{\s*endfor\s*\}\}",
        RegexOptions.Compiled | RegexOptions.Singleline);
    
    public static string Render(string template, Dictionary<string, object> data)
    {
        string result = template;
        
        // 处理循环
        result = ProcessLoops(result, data);
        
        // 处理变量替换
        result = ProcessVariables(result, data);
        
        return result;
    }
    
    private static string ProcessLoops(string template, Dictionary<string, object> data)
    {
        return LoopPattern.Replace(template, match =>
        {
            string itemVar = match.Groups[1].Value;
            string listVar = match.Groups[2].Value;
            string loopTemplate = match.Groups[3].Value;
            
            if (!data.ContainsKey(listVar) || !(data[listVar] is IEnumerable<object> list))
                return "";
            
            var result = new System.Text.StringBuilder();
            foreach (var item in list)
            {
                var loopData = new Dictionary<string, object>(data)
                {
                    [itemVar] = item
                };
                
                string processedLoop = ProcessVariables(loopTemplate, loopData);
                result.Append(processedLoop);
            }
            
            return result.ToString();
        });
    }
    
    private static string ProcessVariables(string template, Dictionary<string, object> data)
    {
        return VariablePattern.Replace(template, match =>
        {
            string varName = match.Groups[1].Value;
            
            if (data.ContainsKey(varName))
            {
                return data[varName]?.ToString() ?? "";
            }
            
            return match.Value;  // 保持原样如果变量不存在
        });
    }
    
    static void Main()
    {
        // 简单变量替换
        string simpleTemplate = "Hello, {{name}}! Today is {{date}}.";
        var simpleData = new Dictionary<string, object>
        {
            ["name"] = "Alice",
            ["date"] = DateTime.Now.ToString("yyyy-MM-dd")
        };
        
        Console.WriteLine("简单模板:");
        Console.WriteLine(Render(simpleTemplate, simpleData));
        
        // 循环模板
        string loopTemplate = @"
购物清单:
{{for item in items}}
- {{item}}
{{endfor}}

总共 {{count}} 项商品。
";
        
        var loopData = new Dictionary<string, object>
        {
            ["items"] = new List<object> { "苹果", "香蕉", "牛奶", "面包" },
            ["count"] = 4
        };
        
        Console.WriteLine("\n循环模板:");
        Console.WriteLine(Render(loopTemplate, loopData));
        
        // 复杂模板
        string complexTemplate = @"
用户报告 - {{reportDate}}

用户: {{user.name}} ({{user.email}})
注册日期: {{user.registerDate}}

最近订单:
{{for order in orders}}
  订单 #{{order.id}} - {{order.date}} - ¥{{order.amount}}
{{endfor}}

总订单数: {{orderCount}}
总金额: ¥{{totalAmount}}
";
        
        var complexData = new Dictionary<string, object>
        {
            ["reportDate"] = DateTime.Now.ToString("yyyy-MM-dd"),
            ["user"] = new Dictionary<string, object>
            {
                ["name"] = "张三",
                ["email"] = "zhangsan@example.com",
                ["registerDate"] = "2023-01-15"
            },
            ["orders"] = new List<object>
            {
                new Dictionary<string, object> { ["id"] = "001", ["date"] = "2023-12-20", ["amount"] = "299.00" },
                new Dictionary<string, object> { ["id"] = "002", ["date"] = "2023-12-22", ["amount"] = "156.50" },
                new Dictionary<string, object> { ["id"] = "003", ["date"] = "2023-12-24", ["amount"] = "89.90" }
            },
            ["orderCount"] = 3,
            ["totalAmount"] = "545.40"
        };
        
        Console.WriteLine("\n复杂模板:");
        Console.WriteLine(Render(complexTemplate, complexData));
    }
}

本章小结

本章详细介绍了 C# 中的字符串处理:

关键要点:

  • 字符串特性:不可变性、引用类型、字符串驻留
  • 基本操作:创建、访问、修改、查找、替换、分割
  • 格式化:复合格式化、字符串插值、自定义格式化
  • StringBuilder:高效的字符串构建,适用于大量字符串操作
  • 正则表达式:强大的模式匹配和文本处理工具

最佳实践:

  • 大量字符串操作时使用 StringBuilder
  • 使用字符串插值提高代码可读性
  • 合理使用正则表达式进行复杂文本处理
  • 注意字符串比较时的大小写和文化敏感性
  • 验证用户输入时使用正则表达式

性能考虑:

  • 避免在循环中进行大量字符串连接
  • 预设 StringBuilder 的初始容量
  • 编译常用的正则表达式模式
  • 使用 StringComparison 枚举指定比较方式

下一步: 在下一章中,我们将学习面向对象编程的基础——类和对象。

延伸阅读

本站内容仅供学习和研究使用。