C# Notizen 8 字符串和正则表达式

一、字符串
在C#中,字符串是一系列不可修改的Unicode字符,创建字符串后,就不能修改它。要创建字符串,最常用的方法是声明一个 string 变量,并将一串用引号括起的字符(字符串字面值)赋给它,如下所示。
string myString = “Hello World~”;

ps:字符串暂留
如果在同一个程序集中有两个相同的字符串字面值,那么运行环境将只为该字面值的所有实例创建一个 string 对象。这被称为字符串暂留(string interning),C#编译器使用这种方式来消除重复的字符串字面值,以节省内存空间并减少执行字符串比较所需的时间。
使用相等运算符对字符串字面值进行比较时,字符串暂留可能有时导致意外的结果:

object obj = "String";
string string1 = "String";
string string2 = typeof(string).Name;
Console.WriteLine(string1 == string2);        //true
Console.WriteLine(obj == string1);            //true
Console.WriteLine(obj == string2);            //false

第一项比较检查值是否相当,这意味着它检查两个字符串的内容是否相同。第二和第三项比较检查引用是否相等,因为比较的是object和string。如果在程序中输入上述代码,就将出现两条警告消息:“可能非有意的引用比较;若要获取值比较,请将左边转换为‘string’”。
字符串暂留只适用于字符串字面值,因此 string2 的值不会被暂留,因为它不是字面值。这意味着obj和string2指向内存中的不同对象,因此该引用比较的结果为false。
字符串字面值可包含特殊的转义序列,用于表示不可打印的字符,如制表符和换行符。转义序列以反斜杆(\)打头。如果要在字符串字面值中包含反斜杆,也必须对其进行转义。
下表列出了C#定义的字符转义序列

转义序列 描述
' 单引号,用于字符字面值
" 双引号,用于字符串字面值
|反斜杠
\0 Unicode字符0
\a 警报(char 7)
\b Backspace(char 8)
\f 换页(char 12)
\n 换行(char 10)
\r 回车(char 13)
\t 水平制表符(char 9)
\v 垂直制表符(char 11)
\uxxxx 对应十六进制值xxxx的字符的Unicode转义序列:还有包含1~4个数字之的变长版本
\uxxxxxxxx 对应十六进制值xxxxxxxx的字符的Unicode转义序列,用于生成Unicode代理区字符(srrogates)

创建字符串字面值时,另一种方法是使用原义字符串(verbatim string literal),这种字符串以@和双引号打头。使用原义字符串的好处是,编译器按原样处理字符串,即使字符串跨越多行或包含转义字符。在原义字符串中,只有双引号需要转义—使用两个双引号表示,以便编译器知道字符串的终止位置。

编译器遇到原义字符串时,将它转换为合适的转义字符串。如下演示了4个字符串,其中前两个等价,虽然原义字符串更容易阅读。后两个字符串也等价,其中multipleLine2是转换后的字符串字面值。

string stringLiteral = "\\Microsoft Visual Studio Code\\VC#";   
string verbatimLiteral = @"\Microsoft Visual Studio Code\VC#";    
string multipleLines = @"This is a ""line"" of text.    And this is the second line.";
string multipleLines2 = "This is a \"line\" of text.\nAnd this is the second line.";

ps:ToString方法
还可调用ToString方法来创建字符串。由于这个方法是在System.Object中声明的,因此每个对象都有它,但其默认实现为返回类名。所有预定义的类型都重写了ToString,以提供有意义的字符串表示。

1.1 空字符串
未赋值的字符串变量为 null,空字符串与此不同,它是在双引号之间没有任何字符的字符串(“”)。
ps:使用String.Empty还是”"

String.Empty 和“”之间没有差别,使用哪一个取决于个人喜好,但String.Empty通常更容易理解。
要判断字符串是否为空,最快捷、最简单的方法是检查其Length属性是否为零。然而,由于字符串属于引用类型,因此字符串变量的值可能为 null,如果试图访问这种字符串变量的Length属性,就将导致运行阶段错误。鉴于经常需要判断字符串是否为空,C#提供了静态方法String.IsNullOrEmpty,如下所示

public static bool IsNullOrEmpty(string value)
{    
    if (value != null)    
    {        
        return (value.Length == 0);    
    }    
    return true;
}

另外,还经常需要判断字符串是否只包含空格,为此可使用静态方法String.IsNullOrWhite Space,如下所示

public static bool IsNullOrEmpty(string value)
{    
    if (value != null)    
    {        
        for (int i=0; i < value.Lenth;i++)        
        {            
            if (!char.IsWhiteSpace(value[i]))            
            {                
                return false;            
            }        
        }    
    }    
    return true;
}

使用方法String.IsNullOrEmpty和String.IsNullOrWhiteSpace有助于确保代码正确、易读和一致,因此每当需要判断字符串是否为null、为空或只包含空格字符时,都应使用它们。

1.2 字符串操作

System.String 类提供了大量的方法和属性,可用于操作字符串。实际上,System.String定义了40多个公有成员。
虽然字符串属于基本数据类型,且通常将字符串数据作为一个整体进行操作,但是字符串毕竟是由字符组成的。要判断字符串包含多少个字符,可使用Length属性。不同于其他语言(如C和C++)中的字符串,C#字符串没有包含终止字符。由于字符串是由字符组成的,因此可通过位置访问其中的各个字符,就像字符串是字符数组一样。
提取子串
子串是字符串的一部分,System.String提供了多个方法可用于查找和提取子串。
为提取子串,String提供了一个重载的Substring方法,让你能够指定起始字符位置,还可指定要提取的子串长度。如果没有指定长度,就将从指定的起始位置提取到字符串末尾。
第一个子串从字符位置10开始,到字符串末尾结束,结果为 brown fox;第二个子串为 quick。

string original = "The quick brown fox";
string substring = original.Substring(10);
string substring2 = original.Substring(4, 5);

以这种方法提取子串很灵活,尤其是结合使用其他方法找出字符在字符串中的位置时。
方法IndexOf和LastIndexOf分别指出指定的字符或字符串首次和最后一次出现的位置。如果要确定一组给定字符中的任何一个首次或最后一次出现的位置,就可以使用方法 IndexOfAny和LastIndexOfAny。如果找到匹配的字符或字符串,就将返回该字符或字符串的起始位置的索引(更直观的说法是偏移量),否则将返回-1。如果搜索的字符串或字符为空,就将返回0。

比较字符串
要对字符串进行比较,以判断一个字符串是否等于或包含另一个字符串,可使用方法Compare、CompareOrdinal、CompareTo、Contains、Equals、EndsWith和StartsWith。
静态方法Copmare有10个重载版本,让您能够控制比较的很多方面,如区分大小写、区域敏感、从什么地方开始比较以及最多比较多少个字符。
ps:字符串比较规则
默认情况下,使用任何Compare方法时,都以区分大小写和区域敏感的方式进行比较。使用相等运算符==时,总是按序号排序规则(ordinal)进行比较。
如果要根据数字序列值对字符串进行比较,可使用重载的静态方法CompareOrdinal(总共有两个版本)。调用该方法时,可指定从两个字符串的什么地方开始比较以及最多比较多少个字符。
方法CompareTo将当前字符串与指定的字符串进行比较,并返回一个整数值,它指出当前字符串在排序顺序中位于指定字符串之前、之后还是同一个位置。
方法Contains使用序号排序规则(ordinal sorting rules)进行搜索,能够判断当前字符串是否包含指定字符串。如果找到了指定字符串或指定字符串为空,那么该方法将返回true。
方法StartsWith和EndsWith(它们总共有6个重载版本)能够判断当前字符串的开头或结尾是否与指定字符串匹配。就像Compare方法一样,也可指定比较时是否区分大小写以及要使用的区域规则。

ps:改变大小写
虽然字符串比较方法让您能够执行区分大小写的比较,但是也可将字符串转换为全部大写或全部小写。这不断有助于比较字符串,还有助于将字符串数据的表示标准化。

要改变大小写,标准方式是使用方法ToUpperInvariant,它使用固定区域性的大小写规则将字符串转换为全部大写。要将字符串转换为全部小写,最好使用方法ToLowerInvariant,它使用固定区域性的大小写规则。除带invariant的方法外,还可使用方法ToUpper和ToLower,它们使用当前区域或指定区域的大小写规则,这取决于您使用的是哪个重载版本。
修改字符串的某些部分
除经常需要比较字符串外,有时候还需要修改字符串。由于字符串是不可变的,因此这些方法实际上返回一个新字符串,而不是修改当前字符串。
要删除字符串中的空格和其他字符,可使用方法Trim、TrimEnd 或TrimStart。TrimEnd和TrimStart分别删除当前字符串开头或末尾的空格,而Trim将两端的空格都删除。
要将字符串扩展(填充)到特定的长度,可使用方法PadLeft或PadRight。默认情况下,这些方法使用空格填充,但是它们都有重载版本,让您能够指定要使用的填充字符。
String 类还提供了一组重载的方法,让您能够通过删除或替换现有字符串中的字符来创建新的字符串。方法Remove从字符串的指定位置开始删除,直到到达字符串末尾或删除了指定数量的字符。方法 Replace 将指定的字符或字符串都替换为另一个字符或字符串,它执行序号搜索,即区分大小写,但是不区分区域性。

字符串拼接、串联和拆分
前面介绍了多种使用字符串字面值和子串创建新字符串的方法,还可通过合并现有字符串来创建新字符串,称之为字符串拼接(concatenation)。
ps:使用加法运算符拼接字符串
加法运算符实际上调用方法Concat的合适重载版本。
通常以两种方式拼接字符串。最常见的方式是使用重载的加法运算符(+)拼接多个字符串;也可使用方法Concat的9个重载版本之一,它让您能够拼接任意数量的字符串。如下代码演示了这两种拼接方法。

string string1 = "this is " + " basic concatenation.";
string string2 = String.Concat("this", "is", "more", "advanced","concatenation");

与拼接紧密相关的一种概念是串联(join)字符串,这种概念使用方法Join。不同于方法Concat,方法Join将一组指定的字符串拼接起来,同时在字符串之间加上指定的分隔符。

如果说串联是合并一组字符串,那么相反的操作就是根据分隔字符将字符串拆分成数量不确定的子串,这是使用方法Split完成的,这个方法接受一组字符或字符串并将其视为分隔符。
如下代码将一系列字符串串联起来,然后基于相同的分隔符将字符串拆分。首先,创建了一个包含10个字符串的数组,并使用分隔符#将这些字符串串联起来。然后,基于分隔符#将得到的字符串进行拆分,并将所有单词显示出来—每个单词占一行。

string[] strings = new string[10];        
for (int i = 0; i <10;i++)       
{            
    string[i] = String.Format("{0}",i * 2);        
}        
string joined = String.Join("#",strings);        
Console.WriteLine(joined);        
foreach (string word int joined.Splite(new char[] {    '#'    }))        
{            
    Console.WriteLine(word);
}

二、使用StringBuilder创建可变的字符串
由于字符串是不可变的,因此每当执行字符串操作时,都将创建新的临时字符串。为创建可变字符串,以免操作它时无需创建新字符串,C#提供了StringBuilder类。如果要拼接的字符串数量是固定的,那么使用 string 更合适;如果要拼接的字符串数量不确定(如迭代语句中),那么使用StringBuilder更合适。
StringBuilder 支持在当前字符串末尾附接数据、在指定位置插入数据、替换数据以及从当前字符串删除数据。要附接数据,可使用方法Append或AppendFormat的重载版本之一。
方法Append将对象的文本或字符串表示加在当前字符串末尾;方法AppendFormat支持使用复合格式化(composite formatting)在当前字符串末尾追加文本。由于方法AppendFormat使用复合格式化,因此可以向它传递一个格式字符串
如下所示使用StringBuilder字符串串联和分拆

StringBuilder stringBuilder = new StringBuilder();        
for(int i=0;i<10;i++)        
{            
    stringBuilder.AppendFormat("{0}#",i*2);        
}        //Remove the trailing '#' character.       
stringBuilder.Remove(stringBuilder.Length - 1,1);        
string joined = String.Join("#",stringBuilder.ToString());        
Console.WriteLine(joined);        
foreach(string word int joined.Split(new char[] {    '#'    }))        
{            
    Console.WriteLine(word);
}

要插入数据,可使用方法 Insert 的重载版本之一。插入数据时,必须指定要在当前StringBuilder的什么位置插入。要删除数据,可使用Remove方法,并指出从什么位置开始删除以及要删除多少个字符。要将当前StringBuilder中的字符替换为另一个字符,可使用方法Replace的重载版本之一。方法Replace还支持对当前StringBuilder的子串中的字符进行替换,其中子串是使用起始位置和长度指定的。
ps:StringBuilder的容量
在幕后,StringBuilder存储在缓冲区中,以便能够支持拼接。仅当缓冲区没有足够的空间容纳新数据时,才需要给StringBuilder分配额外的内存。
内部缓冲区的默认大小(容量)为16个字符。当缓冲区已满时,将分配额外的缓冲区空间,以容纳更多的字符,新分配的缓冲区空间大小由容量指定。StringBuilder还有最大容量,其值为Int32.Maxvalue,即231个字符。
当前字符串的长度可使用属性Length设置。如果设置的Length值比当前容量大,容量将自动改变。同样,通过将 Length 设置成比当前容量小,将截断当前字符串。

三、类型格式化
通过设置格式,可将类实例、结构或枚举值转换为字符串表示。从System.Object派生而来的每种类型都自动继承了一个没有参数的ToString方法,这个方法默认返回类型的名称。所有预定义的值类型都重写了ToString方法,使其返回值的字符串表示。
ToString 返回类型的名称通常没有意义,您可重写 ToString 方法,使其返回值的字符串表示
如下的Contact类重写了ToString方法

class Contact    
{        
    private string firstName;        
    private string lastName;        
    public override string ToString()        
    {            
        return firstName + " " + lastName;        
    }
}

ps:重写ToString方法
给自己创建的类重写ToString方法前,务必知道这样一点:通过调试器查看对象时,Visual Studio调试工具大量使用ToString来确定将该对象显示为什么样的值。
对象的值通常有多种表示,ToString 允许通过参数传递一个格式字符串,以指定字符串表示是什么样的。格式字符串包含一个或多个格式说明符,它们定义了字符串表示应该是什么样的。

3.1 标准格式字符串
标准格式字符串包含一个格式说明符和一个可选的精度说明符,其中格式说明符是单个字符,而精度说明符影响结果中显示的位数。精度说明符可以是0~99的任何整数。所有数值类型、日期和时间类型以及枚举类型都支持一组预定义的标准格式字符串,其中包括标准格式说明符G,它表示值的常规字符串表示。
标准格式说明符:

格式说明符 描述
G、g 常规字符串表示
对于所有的数值类型,结果为最紧凑的定点表示法或科学计数法。精度说明符制定了有效位数
对于所有日期和时间类型,表示常规日期/时间模式。G表示长时间模式,而g表示短时间模式
对于枚举类型,在可能的情况下显示字符串值,否则显示整数值。如果定义枚举时制定了特性Flags,将每个有效枚举的字符串值拼接起来,并用逗号分隔;如果没有指定Flags特性,就将无效枚举值显示为整数
X、x 对于整数类型,结果为十六进制表示。精度说明符制定了位数。
对于枚举值,显示为十六进制表示。必要时添加前导零,以确保长度最少8位
D、d 对于整数类型,结果为十进制表示和可选的符号。精度说明符制定了最少位数
对于枚举类型,显示为最短的整数值
E、e 只有数值类型支持它,结果为科学计数法表示。精度说明符制定了小数位数,默认为6位。
F、f 对于所有的数值类型,结果为整数部分、小数部分和可选的符号。精度说明福指定了小数位数
对于日期和时间类型,表示完整日期/时间模式。F表示长时间模式,而f表示短时间模式
对于枚举类型,尽可能显示为字符串值。如果值为一系列有效枚举值之和,就将其表示为这些有效枚举值对应的字符串的拼接,并用逗号将字符串分隔(即使没有指定Flags特性也如此);否则,显示为整数值
N、n 只有数值类型支持。结果为整数部分、小数部分、千位分隔符、小数点和可选的负号。精度说明符制定了小数位数
P、p 只有数值类型支持。结果为原数值的100倍和百分符号。精度说明符制定了小数位数
R、r 对于Single、Double和BigInteger,结果为原数值的字符串表示,并忽略精度说明符
对于日期和时间类型,表示RFC1123模式
M、m 只有日期和时间类型支持,表示月/日模式
O、o 只有日期和时间类型支持,表示返回日期/时间模式
s 只有日期和时间类型支持,表示可排序日期/时间模式
t 只有日期和时间类型支持,表示短时间模式
T 只有日期和时间类型支持,表示长时间模式
u 只有日期和时间类型支持,表示通用可排序日期/时间模式
U 只有日期和时间类型支持,表示通用完整日期/时间模式
Y、y 只有日期和时间类型支持,表示年/月模式

使用标准格式字符串设置了一个Days枚举值的格式:

    Days days = Days.Monday;
    string[] formats = {"G", "F", "D", "X"};   
    foreach (string format indexer formats)   
{        
    Console.WriteLine(days.ToString(format));
}

对于自己创建的类,除重写方法ToString外,还可定义标准格式说明符,方法是定义一个ToString(string)方法。类应支持下列功能:
格式说明符G表示常规格式。重写不接受任何参数的方法ToString时,应让它调用ToString(string),并传递标准格式字符串G。
如果格式字符串为null,就应将其视为相当于指定了格式说明符G。

如下使用ToString支持标准格式字符串

struct float Degress;public Celsius(float temperature)
{    
    this.Degrees = temperature;
}
public string ToString()
{    
    return this.ToString("C");
}
public string ToString(string format)
{    
    if (String.IsNullOrWhiteSpace(format))    
    {        
        format = "C";    
    }    
    format = format.ToUpperInvariant().Trim();    
    switch(format)    
    {        
        case "C":        
        case "c":            
            return this.Degrees.ToString("N2") +" "C";                
        case "F":        
        case "f":            
            return (this.Degrees *9 / 5 + 32).ToString("N2") +" "F";            
        case "K":        
        case "k":            
            return (this.Degrees +273.15f).TosString("N2") +""K";            
        default:            
            throw new FormatExcpetion();    
     }
}

3.2 自定义格式字符串
自定义格式字符串由一个或多个自定义格式说明符组成,定义了值的字符串表示。如果格式字符串只包含一个自定义格式说明符,就应在它前面加上百分符号(%),以免与标准格式说明符混淆。
所有数值类型以及日期和时间类型都支持自定义格式字符串,而很多标准日期和时间格式字符串还是自定义格式字符串的别名。使用自定义格式字符串时,可通过组合多个自定义格式说明符来定义格式,这提供了极大的灵活性。
自定义格式说明符:

格式说明符 描述
0 只有数值类型支持。如果有相应的数字,就使用数字替换0;否则,在结果中保留0
# 只有数值类型支持。如果有相应的数字,就使用数字替换#;否则,不出现在结果中
. 只有数值类型支持,指定小数点在结果中的未知
, 只有数值类型支持。作为千位分隔符时,在千位组之间插入本地化千位分隔符:作为数字比例换算说明符时,每指定一个逗号,就将数字除以1000。要用作数字比例换算说明符,必须紧邻显示或隐式小数点左侧
% 只有数值类型支持。将数字乘以100,并插入一个本地化百分符号
只有数值类型支持。将数字乘以1000,并插入一个本地化千分符号。‰相当于Unicode符号U+2030
E0、E + 0、E - 0、
e0、e + 0、e - 0
只有数值类型支持。如果后面至少跟一个零,就使用指数表示法显示结果。E和e表示使用大写还是小写的指数符号,而后跟多少个零表示指数至少有多少位。加号(+)表示指数前面总是有符号,而减号(-)表示仅当指数为负时才在指数前面加上符号
; 只有数值类型支持。用于分隔多个部分,这些部分分别制定正数、负数和零的格式。如果只包含一部分(默认设置),那么这部分将用于设置所有制的格式;如果有两部分,那么第一部分用于设置正值和零的格式,第二部分用于设置负值的格式;如果包括三部分,那么第一部分用于设置正值的格式,第二部分用于设置负值的格式,第三部分用于设置零的格式
d 只有日期和时间类型支持,显示一月的哪天,用1~31表示
dd 只有日期和时间类型支持,显示一月的哪天,用01~31表示
ddd 只有日期和时间类型支持,显示星期几的缩写
dddd 只有日期和时间类型支持,显示星期几的完整名称
g、gg 只有日期和时间类型支持,显示纪元
h 只有日期和时间类型支持,显示采用12小时制的小时,用0~11表示
hh 只有日期和时间类型支持,显示采用12小时制的小时,用00~11表示
H 只有日期和时间类型支持,显示采用24小时制的小时,用0~23表示
HH 只有日期和时间类型支持,显示采用24小时制的小时,用00~23表示
K 只有日期和时间类型支持,显示时区信息
m 只有日期和时间类型支持,显示用0~59表示的分钟
mm 只有日期和时间类型支持,显示用00~59表示的分钟
M 只有日期和时间类型支持,显示用1~12表示的月份
MM 只有日期和时间类型支持,显示月份,用01~12表示
MMM 只有日期和时间类型支持,显示月份的缩写
MMMM 只有日期和时间类型支持,显示月份的完整名称
s 只有日期和时间类型支持,显示用0~59表示的秒
ss 只有日期和时间类型支持,显示用00~59表示的秒
t 只有日期和时间类型支持,显示AM/PM指示符的第一个字符
tt 只有日期和时间类型支持,显示AM/PM指示符
y 只有日期和时间类型支持,显示用0~99表示的年份
yy 只有日期和时间类型支持,显示用00~99表示的年份
yyy 只有日期和时间类型支持,显示至少用3位数表示的年份
yyyy 只有日期和时间类型支持,显示用4位数表示的年份
yyyyy 只有日期和时间类型支持,显示用5位数表示的年份
z 只有日期和时间类型支持,显示与UTC相差多少小时,没有前导零
zz 只有日期和时间类型支持,显示与UTC相差多少小时,对于个位数,将加上前导零
zzz 只有日期和时间类型支持,显示与UTC相差多少小时、多少分钟
: 只有日期和时间类型支持,显示时间分隔符
/ 只有日期和时间类型支持,显示日期分隔符
'字符串'、"字符串" 字符串字面值分隔符。将引号内的字符按原样复制到结果中
转义字符,导致将下一个字符视为字符字面值,而不是自定义格式说明符
其他 其他字符都按原样复制到结果中

3.3 复合格式化
使用复合格式化的方法接受一个复合格式字符串和一个对象列表作为参数。复合格式字符串定义了一个模板,它由固定文本和带索引的占位符组成,其中带索引的占位符称为格式项,对应于列表中的对象。使用复合格式化时,指定的格式项不能多于列表中的对象,但是列表中的对象可比格式项多。

格式项的语法:

{index[,alignment][:formatString]}

ps:index和大括号是必不可少的
索引对应于参数列表中对象的位置。索引从零开始,但是多个格式项可使用相同的索引,而格式项可以任何顺序排列,并可指向列表中的任何对象。
alignment 部分是可选的,它指定了首选的字段宽度。如果为正值,字段就将右对齐;如果为负值,字段就将左对齐。如果指定的值比格式化后的字符串长度小,就将忽略alignment值。
formatString部分使用标准格式字符串或自定义格式字符串。如果没有指定,就将使用常规格式说明符G。

举个栗子

Celsius temp = new Celsius(28);

//Using composite formatting width String.Format.
string resault = String.Format("On {0:d}, the high temperature was {1}.", DateTime.Today,temp);
Console.WriteLine(result);

//Using composite formatting width Console.WriteLine.
Console.WriteLine ("On {0:d}, the high temperature was {1}.", DateTime.Today,temp);

四、正则表达式

    正则表达式常被称为模式,描述了一组字符串。可将正则表达式应用于字符串,以确定该字符串是否与指定的模式匹配、返回一个或一系列子串、返回对原始字符串修改后得到的新字符串。

ps:正则表达式的兼容性
.NET Framework中的正则表达式与Perl 5正则表达式兼容,包含其他正则表达式实现(如Perl和awk)中最受欢迎的功能,还新增了其他实现中没有的功能。
正则表达式本身就是一种编程语言,用于操作文本并针对文本操作进行了优化,这是使用字面字符和元字符(metacharacter)实现的。字面字符指的是目标字符串必须与之匹配的字符,而元字符正则表达式分析器如何行动。表达式分析器负责解释正则表达式并将其应用于目标字符串。这些元字符赋予了正则表达式灵活性和强大的处理功能。

如下表是常用正则表达式的元字符

元字符 描述
. 与任何一个字符匹配,但换行符(\n)除外
[] 与包含在方括号内的任何一个字符匹配,还可使用字符“-”指定匹配的字符范围
[^] 与任何一个不包含在方括号内的字符匹配
^ 指定从行首开始匹配
$ 指定匹配的内容应位于行尾
\w 匹配一个单词字符,与[a-zA-z_0-9]等价
\W 匹配非单词字符
\s 匹配空白字符,相当于[\n\r\t\f]
\S 匹配非空白字符
\d 匹配一个十进制数字,相当于[0-9]
\D 匹配非十进制数字
* 匹配零或多个它前面的元素
+ 匹配一个或多个它前面的元素
? 匹配零或一个它前面的元素
{n} 匹配/n个它前面的元素
{n,} 匹配/n个或更多个它前面的元素
{n,m} 匹配/n-m/个它前面的元素
匹配用竖线分隔的表达式之一
() 定义一个未命名捕获组
(?<name>)
(?'name')
定义一个命名捕获组
(?<number>)
(?'number')
定义一个编号捕获组

4.1 C#中的正则表达式
在.NET Framework中,正则表达式是通过命名空间 System.Text.RegularExpression中的几个类实现的,这些类让您能够分析和应用正则表达式以及使用捕获组。
4.1.1 Regex类
Regex类提供了正则表达式分析器和引擎的实现,它将正则表达式应用于输入字符串。通过使用这个类,可以快速分析大量文本,看其是否符合特定模式,还可轻松地提取和编辑子串。
Regex 类提供了实例成员和静态成员,让您能够以两种不同的方式使用它。当您创建Regex 类的实例时,不会编译和缓存表达式模式;但是当您使用静态方法时,将编译和缓存表达式模式。默认情况下,正则表达式引擎将缓存最近使用的15个静态正则表达式。如果需要大量使用一组固定的正则表达式,就应使用静态方法,而不是相应的实例方法。

4.1.2 Match和MatchCollection类
使用Regex类的Match方法将正则表达式应用于字符串时,将用Match类的实例表示第一个匹配项。MatchCollection包含一组Match实例,这些Match是通过重复应用正则表达式找到的匹配项。

4.1.3 Group和Capture类
Match.Groups属性表示单个匹配项中所有的捕获组。每个捕获组都是一个Group实例,而Group实例包含一组Capture对象,这些对象可通过Captures属性获取。Capture表示单个子表达式匹配返回的结果。

4.2 使用正则表达式验证字符串
正则表达式的一种常见用途是验证字符串:检查它是否符合特定模式。为此,可使用方法IsMatch的重载版本之一。

4.3 使用正则表达式搜索子串
正则表达式还可用于搜索与特定正则表达式模式匹配的子串。这种搜索可执行一次,也可重复执行。在前一种情况下,将返回第一个匹配项;在后一种情况下,将返回一系列匹配项。
要以这种方式搜索子串,可使用方法Match或Matches。其中,前者返回第一个匹配项,而后者返回一系列不重叠的匹配项。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容