C#字符串和正则表达式

0.string类

简单字符串操作用string类,对应IL中的System.String类,有很多足够常用的字符串操作,但是频繁操作效率非常低下,所以其它方式的字符串操作同样必不可缺。 每次生成一个新的实例都要申请新的堆资源,和回收旧的资源

1.StringBuilder

频繁更改:频繁创建字符串和多次创建较长的字符串,那么需要用System.TextStringBuilder类提高性能。可以指定最大Capacity,当前长度是Length,当没有指定最大长度时候,那么会翻倍递增内存。但是 只提供了Replace,Append/AppendFormat,Remove的字符串操作。StringBuilder不能转换为String(隐式和显式都不行),唯一转换为String的方法是ToString函数。简单的字符串用string即可。

StringBuilder实例代码:

static void Main()
 {
	   // StringBuilder实际用的长度是Length,当前容量是Capacity超过了会加倍,
	   // 只读属性MaxCapacity是最大容易超过了会报错。
	   // StringBuilder(150, 1000)150是Capacity后面的1000是MaxCapacity
            StringBuilder greetingBuilder =
               new StringBuilder("Hello from all the guys at Wrox Press. ", 150);
            greetingBuilder.Append("We do hope you enjoy this book as much as we enjoyed writing it");

            for(int i = (int)'z'; i>=(int)'a' ; i--)
            {
               char old1 = (char)i;
               char new1 = (char)(i+1);
               greetingBuilder = greetingBuilder.Replace(old1, new1);
            }

            for(int i = (int)'Z'; i>=(int)'A' ; i--)
            {
               char old1 = (char)i;
               char new1 = (char)(i+1);
               greetingBuilder = greetingBuilder.Replace(old1, new1);
            }

            Console.WriteLine("Encoded:\n" + greetingBuilder);
            Console.ReadLine();
  }

2.IFormattable接口的ToString函数

格式化:格式化字符串使用两个有效的接口,称为IFormatProvider和IFormattable来处理。
Console.WriteLine就是调用了String.Format方法来格式化的,String.Format构造格式化的字符串调用了StringBuilder构造函数和StringBuilder的AppendFormat方法,AppendFormat方法会首先检查对象实现了IFormattable接口就调用ToString(string format, IFormatProvider formatProvider),测试失败会调用对象Object.ToString()。

所以自定义类和结构,重写了Object.ToString就可以在Console.WriteLine中输出。所有的基元类型都实现了IFormattable接口。
如果要自定义的类和结构,不调用Object.ToString方法格式化,那么需要实现IFormattable接口的string ToString(string format, IFormatProvider formatProvider)方法
例如:

class MainEntryPoint
   {
      static void Main()
      {
         Vector v1 = new Vector(1,32,5);
         Vector v2 = new Vector(845.4, 54.3, -7.8);
		 // 传入:IJK,:VE,:N格式化说明字符
         Console.WriteLine("\nIn IJK format,\nv1 is {0,30:IJK}\nv2 is {1,30:IJK}", v1, v2);
         Console.WriteLine("\nIn default format,\nv1 is {0,30}\nv2 is {1,30}", v1, v2);
         Console.WriteLine("\nIn VE format\nv1 is {0,30:VE}\nv2 is {1,30:VE}", v1, v2);
         Console.WriteLine("\nNorms are:\nv1 is {0,20:N}\nv2 is {1,20:N}", v1, v2);
		 
		 Console.ReadLine();
      }
   }

   // 需要继承System.IFormattable接口
   struct Vector : IFormattable
   {
      public double x, y, z;

      public Vector(double x, double y, double z)
      {
         this.x = x;
         this.y = y;
         this.z = z;
      }
    // 重写System.IFormattable的string ToString(string format, IFormatProvider formatProvider)函数
	// IFormatProvider formatProvider类型系统默认根据当前文化背景提供,不需要处理。
      public string ToString(string format, IFormatProvider formatProvider)
      {
         if (format == null)
            return ToString();
         string formatUpper = format.ToUpper();
         switch (formatUpper)
         {
            case "N":
               return "|| " + Norm() + " ||";
            case "VE":
               return String.Format("( {0:E}, {1:E}, {2:E} )", x, y, z);
            case "IJK":
               StringBuilder sb = new StringBuilder(x.ToString(), 30);
               sb.Append(" i + ");
               sb.Append(y.ToString());
               sb.Append(" j + ");
               sb.Append(z.ToString());
               sb.Append(" k");
               return sb.ToString();
            default:
               return ToString(); 
         }
      }

3.RegularExpressions

正则表达式:对于字符串复杂的查找,替换,提取某个类型的或者具体的字符串,那么可以用正则表达式来处理,在System.Text.RegularExpressions命名空间中。
正则表达式中的字符串查找替换提取删除操作,都可以使用String和StringBuilder来做到,但是有时候字符串操作比较复杂,需要大量的这些基本字符串的操作,如果用正则表达式,则可以用很少的代码解决。
正则表达式经典应用:
1)字符串模式验证,例如是否是邮箱模式,是否是有效的身份证。
2)多个元组直接存储需要的信息,或用或形式,提取出多个需要要的信息。
3)字符串的一些指定的替换。


js中的正则表达式:
RegExp对象由字符模式和搜索范围组成。
字符串模式的类型:
(1). 字符和模式,连续出现组合关系:字符串长度确定的模式(包括确定的字符串和模糊匹配的字符)"%d%d/%d%d/%d%d%d%d", “Jackson”,本身就是表达了与的关系。
(2).自定义逻辑组合/或/非:字符串模式中任意一个都遍历目标串的模式([], (),逻辑与或|, ^非),[AEIOUaeiou]匹配元音,“([a-z][A-Z][0-9])+”()是将几个或组合在一起匹配aB0。”[to|too|2]”;^在[]内为非,否则为定位符号;与可以用或来表达/[^\w\s]/g。
(3). 数量:字符模式个数的修饰,+,-,*,?,{n}元符号;“fo+”与football匹配,+为至少有一个或者多个这样的字符。
(4). 位置:字符串模式位置的修饰,^,$,\b, \B;”ar$”和car匹配。
(5). 转义符号\, “Th\*”与Th*匹配,常规模式在字符串中也要”\\s”,前面的\也是转义字符。


搜索范围有i, g, m:
i 执行对大小写不敏感的匹配。
g 执行全局匹配(查找所有匹配而非在找到第一个匹配后停止)。
m 执行多行匹配。

C#中使用正则表达式模式和js一致,要用模式中的\符号,那么需要将输入转换到字符串时候保持,所以需要"\\"或者@"\"。
C#中的正则表达式需要用到RegularExpressions命名空间,Regex对象, MatchCollection字符匹配后枚举结果,Match单个匹配字符串封装。
正则表达式使用实例:

using System;
using System.Text.RegularExpressions;

namespace Wrox.ProCSharp.RegularExpressionPlayaround
{
   class MainEntryPoint
   {
      static void Main()
      {
         Find3();
         Console.ReadLine();
      }

      static void Find1()
      {
         const string text = @"XML has made a major impact in almost every aspect of 
            software development. Designed as an open, extensible, self-describing 
            language, it has become the standard for data and document delivery on 
            the web. The panoply of XML-related technologies continues to develop 
            at breakneck speed, to enable validation, navigation, transformation, 
            linking, querying, description, and messaging of data.";
			
         const string pattern = @"\bn\S*ion\b";
		 // matches正则表达式运算返回的结果
         MatchCollection matches = Regex.Matches(text, pattern, 
            RegexOptions.IgnoreCase | RegexOptions.IgnorePatternWhitespace | RegexOptions.ExplicitCapture);
			
		// 输出结果
         WriteMatches(text, matches);
      }		

      static void Find2()
      {
         const string text = @"XML has made a major impact in almost every aspect of 
            software development. Designed as an open, extensible, self-describing 
            language, it has become the standard for data and document delivery on 
            the web. The panoply of XML-related technologies continues to develop 
            at breakneck speed, to enable validation, navigation, transformation, 
            linking, querying, description, and messaging of data.";
			
         const string pattern = @"\bn";
         MatchCollection matches = Regex.Matches(text, pattern, 
            RegexOptions.IgnoreCase);
			
         WriteMatches(text, matches);
      }
	  
	  static void Find3()
	  {
		    // 1)从文本中提取出指定的模式
		  Console.WriteLine("从文本中提取出指定的模式");
		  const string urlText = "sljflsfj sfjlsjf fj http://blog.csdn.net/blues1021";
		  const string pattern = @"\b(\S+)://([^:]+)(?::(\S+))?\b";
		  MatchCollection matches = Regex.Matches(urlText, pattern, 
            RegexOptions.IgnoreCase);
			
		  WriteMatches(urlText, matches);
		
		
		// 2)截取需要的字符串信息 类似C原因中的sscanf
	     // string url = "http://www.contoso.com:8080/letters/readme.html";
		 // const string pattern2 = @"^(?\w+)://[^/]+?(?:\d+)?/";
		 Console.WriteLine("截取需要的字符串信息 类似C原因中的sscanf");
		 const string textCapture = "http://blog.csdn.net/blues1021";
		 const string patternCapture = @"^(?\w+)://?(?
[^/]+)/?(?\S+)"; Regex r = new Regex(patternCapture,RegexOptions.None, TimeSpan.FromMilliseconds(150)); Match m = r.Match(textCapture); if(m.Success) { string strProtocal = m.Result("${proto}"); string strAddress = m.Result("${address}"); string strName = m.Result("${name}"); Console.WriteLine("Parse Protocal: " + strProtocal + ", Address:" + strAddress + ", Name:" + strName ); // Console.WriteLine(m.Result("${proto}:${port}")); } } static void WriteMatches(string text, MatchCollection matches) { Console.WriteLine("Original text was: \n\n" + text + "\n"); Console.WriteLine("No. of matches: " + matches.Count); foreach (Match nextMatch in matches) { // nextMatch是当前匹配的字符的委托对象,Match.Index属性 int index = nextMatch.Index; // Match.ToString功能 string result = nextMatch.ToString(); // 匹配在字符串中间,字符前面取5个字符索引长度,否则取当前字符索引长度,charsBefore是相对位置 int charsBefore = (index < 5) ? index : 5; // 剩下的字符长度 int fromEnd = text.Length - index - result.Length; // 剩下的字符长度太小了就是剩下字符长度,否则取5个长度 int charsAfter = (fromEnd < 5) ? fromEnd : 5; // 需要展示的字符长度位置,目的是为了说明该查找提取出来的字符所在原来字符串中的位置。 int charsToDisplay = charsBefore + charsAfter + result.Length; Console.WriteLine("Index: {0}, \tString: {1}, \t{2}", index, result, // 截取附近的字符串 text.Substring(index - charsBefore, charsToDisplay)); } } } }
了解更多的复杂字符串的正则表达式操作,.net也提供了相应的类GroupCollection,CaptureColleciton等。

你可能感兴趣的:(C#.NET)